Component(#70354292616060) expected, got String(#70354278277000)
以下のオブジェクト「Machine」の作成時にActiveRecord::AssociationTypeMismatchを取得しました。
目的: 他のモデルを参照するモデルに「属性」を割り当ててみます。
質問: この種の操作のベスト プラクティスは何か、専門家から聞きたいです。
設定:
Rails 3.2.12 / Ruby 1.9.3-p194:
モデル:
class Machine < ActiveRecord::Base
attr_accessible :cpu, :name, :ram
belongs_to :cpu, class_name: "Component", foreign_key: "component_id"
belongs_to :ram, class_name: "Component", foreign_key: "component_id"
end
class Component < ActiveRecord::Base
attr_accessible :name
has_many :machines
end
マシンのビュー:
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :cpu %><br />
<%= f.collection_select :cpu, Component.all, :id, :name %>
</div>
<div class="field">
<%= f.label :ram %><br />
<%= f.collection_select :ram, Component.all, :id, :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
手順:
id:1 name:"cpu1"
&などのコンポーネントにいくつかのオブジェクトを作成しますid:2 name:"ram1"
- machines_path に移動し、プルダウンから cpu1 と ram1 を選択して Machine を作成します。
- 送信時に次のエラーが発生しました
Component(#70354292616060) expected, got String(#70354278277000)
View で :cpu と :ram を :cpu_id と :ram_id に変更しようとしました。その後、エラーなくモデルを作成できます。ただし、マシンから直接 CPU と RAM にアクセスすることはできません。
1.9.3-p194 :001 > Machine.first
Machine Load (0.1ms) SELECT "machines".* FROM "machines" LIMIT 1
=> #<Machine id: 2, name: "test", cpu_id: 1, ram_id: 1, created_at: "2013-05-06 16:42:47", updated_at: "2013-05-06 16:42:47">
1.9.3-p194 :002 > Machine.first.cpu
Machine Load (0.2ms) SELECT "machines".* FROM "machines" LIMIT 1
=> nil
1.9.3-p194 :003 > Machine.first.ram
Machine Load (0.2ms) SELECT "machines".* FROM "machines" LIMIT 1
=> nil
したがって、次のモデルメソッドを作成する必要がありました
class Machine < ActiveRecord::Base
(snip)
def cpu
Component.find_by_id(self.cpu_id)
end
def ram
Component.find_by_id(self.ram_id)
end
その後、期待される出力を得ることができます
1.9.3-p194 :002 > Machine.first.cpu.name
Machine Load (0.2ms) SELECT "machines".* FROM "machines" LIMIT 1
Component Load (0.2ms) SELECT "components".* FROM "components" WHERE "components"."id" = 1 LIMIT 1
=> "CPU1"
しかし、それは冗長だと感じており、これを行うためのより簡単な方法を探しています。
提案があれば感謝します。