【发布时间】:2016-06-21 17:42:02
【问题描述】:
我有以下型号:
class Foo < ActiveRecord::Base
belongs_to :bar
accepts_nested_attributes_for :bar
end
class Bar < ActiveRecord::Base
has_many :foo
end
Bar 包含“对象”,Foo 包含“标签”。
我可以做到以下几点:
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
我可以理解为什么会发生这种情况,但我希望能够使用该功能。我知道我需要添加代码来为 Bar 执行“find_or_create_by”,但我已经有了这个工作,所以我没有把它放在这里,只是我目前遇到的问题。
那么,有没有办法让 Foo 的“查找”只是忽略 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。
我希望这会有所帮助。
【问题讨论】:
-
您可以使用 :where 或任何自定义范围链接 find_or_create_by。您是否尝试过在使用
find_or_create_by之前使用 where 子句? -
嗯,一般来说,嵌套属性曾经是一个 gem,后来被合并到 Rails 中,所以任何适用于 ActiveRecord 的东西都不必使用嵌套属性。您是否仅在具有某些属性的 Bar 对象不存在时才尝试创建 Foo 对象?
-
并非所有代码都在上面。简而言之,我要做的是在 Bar 上运行 find_or_create_by,然后将结果用于 Foo 上的 find_or_create_by。
-
那么我想你应该先在 Bar 上找到,然后如果需要创建它,最后创建 Foo。这是一种直截了当的方式。为了提出更合适的建议,必须了解您实际在做什么。例如,也许 :reject_if for nested_attributes 可以为您工作。
-
在原始帖子中添加了更多信息。
标签: ruby-on-rails nested-attributes belongs-to