Rails attr_accessible does not work for :type?

只愿长相守 提交于 2020-01-03 16:56:39

问题


Im trying set the single table inheritance model type in a form. So i have a select menu for attribute :type and the values are the names of the STI subclasses. The problem is the error log keeps printing:

WARNING: Can't mass-assign these protected attributes: type

So i added "attr_accessible :type" to the model:

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

Doesn't change anything, the ContentItem still has :type=nil after .update_attributes() is called in the controller. Any idea how to mass update the :type from a form?


回答1:


we can override 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")



回答2:


You should use the proper constructor based on the subclass you want to create, instead of calling the superclass constructor and assigning type manually. Let ActiveRecord do this for you:

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

This gives you the benefits of defining different behavior in your subclasses initialize() method or callbacks. If you don't need these sorts of benefits or are planning to change the class of an object frequently, you may want to reconsider using inheritance and just stick with an attribute.




回答3:


Duplex at railsforum.com found a workaround:

use a virtual attribute in the forms and in the model instead of type dirtectly:

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

Worked like a charm.




回答4:


"type" sometimes causes troubles... I usually use "kind" instead.

See also: http://wiki.rubyonrails.org/rails/pages/ReservedWords




回答5:


I followed http://coderrr.wordpress.com/2008/04/22/building-the-right-class-with-sti-in-rails/ for solving the same problem I had. I'm fairly new to Rails world so am not so sure if this approach is good or bad, but it works very well. I've copied the code below.

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"}>


来源:https://stackoverflow.com/questions/1601739/rails-attr-accessible-does-not-work-for-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!