Rails 4 find_or_create_by with accepts_nested_attributes

时间:2016-06-21 17:42:02

标签: ruby-on-rails nested-attributes belongs-to

我有以下型号:

class Foo < ActiveRecord::Base
  belongs_to :bar
  accepts_nested_attributes_for :bar
end

class Bar < ActiveRecord::Base
  has_many :foo
end

栏包含&#39;对象&#39;和Foo包含&#39;标签&#39;。

我可以做以下事情:

f=Foo.create(:label=>"label",:bar_attributes=>{:object=>"mason jar"})

这很好用。

然而,我想要做的是:

f=Foo.find_or_create_by(:label=>"label",:bar_attributes=>{:object=>"mason jar"})

问题是,这会因SQL错误而失败

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: bar_attributes.object: SELECT  "foo".* FROM "foo" WHERE "foo"."label" = ? AND "bar_attributes"."object" = 'mason jar' LIMIT 1

我可以理解为什么会这样,但我希望能够使用该功能。我知道我需要添加代码来执行&#34; find_or_create_by&#34;对于Bar,但我已经有了这个工作,所以我不会把它放在这里,只是我目前遇到的问题。

那么,有没有办法让“找到”&#39;对于Foo只是IGNORE bar_attributes,并且仅在必要时使用它(用于创建)?

或者,还有另一种方法可以实现这一目标吗?

编辑:解释为什么会这样:

我们有两个独立的对象。 Bar是一个独立的对象。 Foo是一个单独的对象类型,它包含一个Bar。

所以,我们可以在Bar中有几条记录:

Mason jar
Shovel
Can of corn

我们可以在Foo中有其他记录:

label: 123 => Bar: Shovel
label: 456 => Bar: Shovel
label: 123 => Bar: Can of corn

Foo中的所有Bar都是有效的Bar,但只有在Foo中带有标签的Bar才是Foo。

所以,基本上,我希望能够运行:

f = Foo.find_or_create_by(:label=>'label',:bar_attributes=>{:object='object'})

并在必要时创建Bar,然后在必要时创建Foo。

我希望这会有所帮助。

1 个答案:

答案 0 :(得分:1)

我想,你可以这样做:

f = Foo.find_or_create_by(label: 'label', bar: Bar.find_or_create_by(object: 'object'))

相当于

f = Foo.find_or_create_by(label:'label',bar_id:Bar.find_or_create_by(object:'object')。id)

您可能希望将其设为两行,以便检查是否已创建Bar(无验证失败)。