我正在尝试在单个数据库字段中保存选项的哈希值。表单能够将数据保存到数据库,但是当我去编辑它时无法再次检索它(例如,除了wp_options字段之外,所有其他字段都是预先填充的)。
class Profile < ActiveRecord::Base
serialize :wp_options
end
这是我的自定义类:
class WP_Options
attr_accessor :wp_name, :wp_desc, :wp_limit
end
以我的形式:
<%= form_for(@profile, :remote => true) do |f| %>
...
<%= f.fields_for :wp_options do |wp_options| %>
<%= wp_options.text_field :wp_name %>
<% end %>
...
在我的控制器中:
@profile = Profile.new(:wp_options => WP_Options.new)
在我的数据库专栏'wp_options'中:
--- !map:ActiveSupport::HashWithIndifferentAccess
wp_name: Test
任何建议都会非常感激。
答案 0 :(得分:11)
实际上这很容易。您需要使用具有reader
方法的类。您可以使用不同的方式创建它,但最简单的方法是使用OpenStruct
类(注意,它将无法查看OpenStruct实例方法中的字段...此类无法重新定义方法)。
在您的表单中,您应该添加:
<%= f.fields_for :wp_options, @profile.wp_options do |wp_options| %>
而不是@profile(如果你有动态变量),你可以使用f.object.wp_options
。
对于模型Profile
,您应该添加wp_options
方法。
def wp_options
OpenStruct.new(self.attributes['wp_options'])
end
在这种情况下,只有序列化的wp_options是Hash类才会有效。
希望有所帮助。
PS。我使用相同的技术,但因为我有type
哈希键,OpenStruct无法创建它,所以我使用了简单的Struct类。我有data
列:
def data
keys = current_data.keys
data = attributes[:data]
Struct.new(*keys).new(*keys.map { |k| data[k] })
end
有点不那么琐碎,但无论如何都采用相同的方法(在此之前我创建了特殊的类,但现在我知道Struct是创建这类东西的更好方法。你可以在这里找到更多的想法:{{3 }})
答案 1 :(得分:1)
对于那些使用Dmitry解决方案的人,在rails 3.0.5上(不确定上一个/下一个版本,所以之前尝试),添加
require 'ostruct'
到您的environment.rb文件,以便包含OpenStruct。
如果您要使用JSON进行序列化,请在您的模型中添加(哦,我对RoR很新,所以请随时仔细检查并建议一个更好的“工作”解决方案然后这个)(我的变量名称已更改为与上面的示例匹配):
before_save :json_serialize
after_save :json_deserialize
after_find :json_deserialize
def json_serialize
self.wp_options = ActiveSupport::JSON.encode(self.attributes['wp_options'])
end
def json_deserialize
unless (self.attributes['wp_options'].nil?)
self.wp_options = ActiveSupport::JSON.decode(self.attributes['wp_options'].to_s)
end
end
最后一点:我真的不确定为什么必须存储到self.wp_options而不是self.attributes ['wp_options'],如果有人能解释它会很酷
答案 2 :(得分:0)
我遇到了同样的问题。我的解决方案如下:
在帮助程序中定义方法:
def wp_options_text_field(profile, wp_options, name)
wp_options.text_field name, :value => profile.wp_options[name]
end
在您看来:
<%= form_for(@profile, :remote => true) do |f| %>
...
<%= f.fields_for :wp_options do |wp_options| %>
<%= wp_options_text_field :wp_name %>
<% end %>
...
这里唯一的问题是你需要为你将使用的每个帮助方法定义方法。在我的情况下,我只使用了2种方法,并没有痛苦。