Active Record Store允许您序列化单个单元格内的参数。
即
class User < ActiveRecord::Base
store :options, accessors: [ :option1, :option2, :another_random_option ]
end
现在,所有访问者都在users表的“options”列中序列化。
u = User.new
u.option2 = 'some option'
u.option2 # => 'some option'
这对我的应用程序非常有用,因为我必须每天创建多个表单,其中90%的表单是相同的(用户名,爱好,兴趣等),然后10%是无架构的(random_option_here) ,another_random_option_in_another_form)。我也从不需要按无模式选项进行排序。
我做的是为90%的表单字段创建了1个表,它们始终是相同的,然后我有另一个表,其中包含最后10%的字段(我有另一个表的原因是因为这是一个belongs_to关系,因此用户在此表中可以有很多行。
<%= form_tag do %>
<%= #render partial form for an object that has non-changing fields %>
...
<%= #render a schema-less partial form based off an ID passed here %>
<% end >
现在唯一的问题是每次我在自定义表单中创建一个新字段时,我必须将该参数添加到Active Record Store访问器,否则我会得到一个方法缺失错误。如果我可以进入并为无模式字段创建尽可能多的View表单并且永远不会更新模型中的访问器,那将是很好的。
所以我的问题是:是否有动态添加所有用户提交的自定义字段到访问者数组,这样如果用户提交字段“some_random_option1221”,“another_option_here”然后我不必进入访问者数组并添加该字段?
谢谢!
答案 0 :(得分:13)
使用rails 4和postgresql以下内容适用于我。通过一些小的调整看起来也可以使用rails 3存储方法。
在给定模型实例拥有的商店哈希中的每个字段键上动态调用store_accessor。如果您的用户模型具有名为hstore类型的选项的列,则您可以访问选项哈希。 (在rails 3中,您可以像问题中的代码一样调用store方法,以使选项方法有效。)
每当用户界面添加新字段时,创建一个方法来执行此操作。然后还调用此方法after_initialize,以便从db加载用户将在加载时设置字段名称访问器。您可能还想调用此方法after_save。
class User < ActiveRecord::Base
after_initialize :add_field_accessors
after_save :add_field_accessors
def add_store_accessor field_name
singleton_class.class_eval {store_accessor :options, field_name}
end
def add_field_accessors
num_fields = options.try(:keys).try(:count) || 0
options.keys.each {|field_name| add_store_accessor field_name} if num_fields > 0
end
end
然后,每个用户实例可以具有不同的store_accessor方法,具体取决于每个用户在该用户的db行的options列中具有的字段。
在您的控制器中,根据您添加/删除/编辑选项的首选用户界面,您可以使用帮助程序方法在用户上构建选项,并从新建,创建,更新等中调用它。
def build_options
@user.options = options_hash
@user.add_field_accessors
end
在rails 3中,不是调用store_accessor,而是调用attr_accessor。
请注意,您将无法调用User.new(:option_1 =&gt;'some_option_value'),因为User类对象没有访问器方法(因为每个用户实例可能具有不同的属性。)< / p>
答案 1 :(得分:0)