Rails attr_accessible不适用于:type?

时间:2009-10-21 15:43:37

标签: ruby-on-rails single-table-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

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

5 个答案:

答案 0 :(得分:20)

我们可以覆盖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")

答案 1 :(得分:9)

您应该使用基于您要创建的子类的正确构造函数,而不是调用超类构造函数并手动分配类型。让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()方法或回调中定义不同行为的好处。如果您不需要这些类型的好处或者计划经常更改对象的类,您可能需要重新考虑使用继承并坚持使用属性。

答案 2 :(得分:6)

railsforum.com上的Duplex发现了一种解决方法:

  

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

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

像魅力一样工作。

答案 3 :(得分:4)

“type”有时会引起麻烦......我通常会使用“kind”。

另请参阅:http://wiki.rubyonrails.org/rails/pages/ReservedWords

答案 4 :(得分:1)

我跟着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:0xb79e89d4 @attrs={:type=>"X"}>