即
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”然后我不必进入访问者数组并添加那个领域?
谢谢!
解决方法
在给定模型实例拥有的商店哈希中的每个字段键上动态调用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中,您将调用attr_accessor,而不是调用store_accessor.
请注意,您将无法调用User.new(:option_1 =>’some_option_value’),因为User类对象没有访问器方法(因为每个用户实例可能具有不同的属性.)