2

アプリケーションに単一テーブル継承を使用しています。私のポリモーフィック タイプは Maintenance で、現在、OilChange という名前のサブタイプが 1 つだけあります。コントローラーの create メソッドでレコードを作成する際に問題が発生しています。これがコードです。

@log = Log.new(params[:log])
@log.maintenance = Maintenance.new(params[:maintenance])

params[:maintenance] ハッシュにはキー {:name, :type} があります。次のように出力することで、それらの存在と値を確認できます

print params[:maintenance][:name]
print params[:maintenance][:type]

:type キーの値として「OilChange」を渡すと、Maintenance レコードのタイプは Maintenance であり、OilChange ではありません。REPL コンソールでレコードを見つけることで確認できます。タイプ フィールドは nil です。次の行を追加することで、思い通りに動作させることができます。

@log.maintenance.type = params[:maintenance][:type]

しかし、それは醜いです。私が疑問に思っているのは、名前フィールドがちょうど見つけるのと同じように、作成メソッドがタイプフィールドを設定しないのはなぜですか?

表示される 2 つのタイプは、私の schema.rb では次のようになります。

create_table "logs", :force => true do |t|
  t.date     "date"
  t.text     "description"
  t.string   "title"
  t.string   "summary"
  t.integer  "car_id"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.integer  "maintenance_id"
  t.integer  "mileage"
end

create_table "maintenances", :force => true do |t|
  t.string   "name"
  t.string   "type"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "oil_brand"
  t.string   "oil_type"
  t.string   "oil_filter_type"

私のモデルはこのように見えます。

class Log < ActiveRecord::Base
belongs_to :car
has_and_belongs_to_many :tags
  belongs_to :maintenance
end

class Maintenance < ActiveRecord::Base
  has_one :log
end

class OilChange < Maintenance
end

ティア!

4

2 に答える 2

3

具体的な答えは、typeRails の多くの特別な属性と同様に、この属性は一括代入から保護されているということです。(:attr_protectedドキュメントを参照してください。)

より一般的な問題に対する答えは、モデルを十分に信頼していないことです。タイプ OilChange のレコードを作成する場合は、Maintenance.newまたはを呼び出さないでくださいMaintenance.createOilChange.new代わりにorを呼び出すOilChange.createと、Rails が型の設定とすべてのバックグラウンド作業を自動的に処理します。

于 2009-10-21T13:30:43.267 に答える
0

次のコードを試してください。

begin
  klass = Module.const_get(params[:maintenance][:type])
  @log.maintenance = klass.new(params[:maintenance])
  if ! @log.maintenance.is_a?(Maintenance)
    @log.maintenance = Maintenance.new(params[:maintenance])
  end
rescue NameError
  @log.maintenance = Maintenance.new(params[:maintenance])
end

データベースに Maintenance のサブクラスのみを含める場合は、Maintenance クラスで次の操作を行います。

class Maintenance < ActiveRecord::Base
  validates_presence_of :type
  # other stuff goes here
end

このコードは、params に間違ったタイプが含まれている場合、無効な Maintenance クラスを作成します。正しいタイプが含まれている場合、指定されたクラスのインスタンスが作成されます。

モデルが名前空間を使用している場合は、使用する代わりに この記事を参照できますModule.const_get

于 2011-04-10T11:33:05.687 に答える