1

Component(#70354292616060) expected, got String(#70354278277000)在下面创建对象“机器”时得到 ActiveRecord::AssociationTypeMismatch ;

目标:尝试将“属性”分配给引用另一个模型的模型。

:我想听专家说这种操作的最佳做​​法是什么。

设置

导轨 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>

程序

  1. 为 Component 创建几个对象,这样id:1 name:"cpu1"&id:2 name:"ram1"
  2. 转到machines_path并从下拉菜单中选择cpu1和ram1来创建机器
  3. 提交时出现以下错误Component(#70354292616060) expected, got String(#70354278277000)

我试图用 :cpu_id 和 :ram_id 更改视图中的 :cpu 和 :ram。此后,我可以毫无错误地创建模型。但是我不能直接从机器访问 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" 

但我觉得这是多余的,正在寻找一种更简单的方法来做到这一点。

欣赏是否有任何建议。

4

2 回答 2

0

First off, having your select boxes work with cpu_id and ram_id is the right thing to do. If you don't then rails will (simplifying slightly) do

machine.cpu = params[:machine][:cpu]

Params are always strings, so this is trying to assign a string to the association, hence the error about it expecting a component but getting a string.

Your second problem is in how you've declared your associations: you've set both ram and cpu associations to use the component_id column to store the id of the corresponding column, which clearly can't work. Instead you probably want the CPU association to use the cpu_id column and the ram association the ram_id column. This is actually the default - remove the foreign key option you're passing to those calls to belongs to and you should be ok.

You associations on component would need a foreign key option though. The simplest thing would be to have one association for the machines that the component acts as CPU for and another for the ram. You might consider setting up single table inheritance, in which case the CPU subclass would only have the association relating to cpu_id and the ram subclass would only have the association relating to ram_id

于 2013-05-06T18:20:45.407 回答
0

因此,如果我没看错,您需要能够在表单中将字段设置为其他模型。

那是嵌套属性。

form_for @components在模型中执行form_for @machinesattr_accessible授予对这些字段的权限Machine

这很有帮助http://railscasts.com/episodes/196-nested-model-form-part-1

于 2013-05-06T17:39:34.853 回答