Rails attr_accessible不适用于:type?

我尝试在表单中设置单表inheritance模型类型。 所以我有一个属性的选择菜单:类型,值是STI子类的名称。 问题是错误日志保持打印:

警告:无法批量分配这些受保护的属性:类型

所以我在模型中添加了“attr_accessible:type”:

class ContentItem < ActiveRecord::Base # needed so we can set/update :type in mass attr_accessible :position, :description, :type, :url, :youtube_id, :start_time, :end_time validates_presence_of :position belongs_to :chapter has_many :user_content_items end 

不改变任何东西,在控制器中调用.update_attributes()之后,ContentItem仍然具有:type = nil。 知道如何从表单中大量更新:type?

我们可以覆盖attributes_protected_by_default

 class Example < ActiveRecord::Base def self.attributes_protected_by_default # default is ["id","type"] ["id"] end end e = Example.new(:type=>"my_type") 

您应该使用基于您要创建的子类的正确构造函数,而不是调用超类构造函数并手动分配类型。 让ActiveRecord为您完成此操作:

 # in controller def create # assuming your select has a name of 'content_item_type' params[:content_item_type].constantize.new(params[:content_item]) end 

这为您提供了在子类initialize()方法或回调中定义不同行为的好处。 如果您不需要这些类型的好处或者计划经常更改对象的类,您可能需要重新考虑使用inheritance并坚持使用属性。

railsforum.com上的双工找到了一个解决方法:

在表单和模型中使用虚拟属性而不是类型为dirtectly:

 def type_helper self.type end def type_helper=(type) self.type = type end 

工作就像一个魅力。

“类型”有时会引起麻烦…我通常使用“善意”代替。

另见: http : //wiki.rubyonrails.org/rails/pages/ReservedWords

我按照http://coderrr.wordpress.com/2008/04/22/building-the-right-class-with-sti-in-rails/来解决我遇到的同样问题。 我是Rails世界的新手,所以我不确定这种方法是好还是坏,但它的效果非常好。 我复制了下面的代码。

 class GenericClass < ActiveRecord::Base class << self def new_with_cast(*a, &b) if (h = a.first).is_a? Hash and (type = h[:type] || h['type']) and (klass = type.constantize) != self raise "wtF hax!!" unless klass < self # klass should be a descendant of us return klass.new(*a, &b) end new_without_cast(*a, &b) end alias_method_chain :new, :cast end class X < GenericClass; end GenericClass.new(:type => 'X') # => #"X"}>