4

単一テーブルの継承モデル タイプをフォームに設定しようとしています。したがって、属性 :type の選択メニューがあり、値は STI サブクラスの名前です。問題は、エラー ログが出力され続けることです。

警告: これらの保護された属性をまとめて割り当てることはできません: type

だから私は "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 を一括更新する方法はありますか?

4

5 に答える 5

20

attribute_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")
于 2010-11-17T03:30:38.330 に答える
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() メソッドまたはコールバックで異なる動作を定義する利点が得られます。この種の利点が必要ない場合、またはオブジェクトのクラスを頻繁に変更する予定がある場合は、継承の使用を再検討し、属性に固執することをお勧めします。

于 2009-10-21T18:22:20.660 に答える
6

railsforum.com の Duplex が回避策を見つけました。

直接入力する代わりに、フォームとモデルで仮想属性を使用します。

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

魅力のように働きました。

于 2009-10-21T18:17:45.807 に答える
4

「type」は時々トラブルを引き起こします... 私は通常、代わりに「kind」を使用します。

参照: http://wiki.rubyonrails.org/rails/pages/ReservedWords

于 2009-10-21T16:20:58.160 に答える
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"}>
于 2010-08-20T05:40:13.457 に答える