在持久性之前通过关联has_many

时间:2015-08-12 20:31:33

标签: ruby-on-rails ruby activerecord

在保持:through关系之前,是否仍然可以返回关联?

以下是类结构的简化版本:

class Foo < ActiveRecord::Base
  has_many :quxes
  has_many :bars, through: :quxes
end

class Bar < ActiveRecord::Base
  # there is no has_many :quxes -- this class doesn't care
end

class Qux < ActiveRecord::Base
  belongs_to :foo
  belongs_to :bar
end

所以,我想调用foo.bars等同于foo.quxes.map(&:bars)

的调用

我正在克隆Foo,但没有保存它们。 Qux通过

old_foo复制到new_foo
new_foo.quxes << old_foo.quxes.map(&:dup)

请注意,上述结果为:

new_foo.quxes.first.foo == new_foo

new_foo.quxes.first.foo_id == old_foo.id

表示关联存在,但尚未保留。

在我看来,你现在应该可以做到:

new_foo.bars # same as new_foo.quxes.map(&:bar)

但实际上它会返回[]

此关联new_foo.bars是否有可能在new_foo之前工作并且其新的quxes已保存?这是:through的预期/理想行为吗?

1 个答案:

答案 0 :(得分:1)

through关系仍然“有用”,因为你可以正常操作它。我认为您的意思是它不包含任何bars添加到任何quxes。这是因为关系bars与关系quxes是分开的,即使它不是独立的。换句话说,bars不仅仅是quxes.map(&:bar),正如你所说的那样;它运行一个完全独立的查询,如:

> puts foo.bars.to_sql
SELECT "bars".* FROM "bars" INNER JOIN "quxes" ON "bars"."id" = "quxes"."bar_id" WHERE "quxes"."foo_id" = 1
> puts new_foo.quxes.to_sql
SELECT "quxes".* FROM "quxes" WHERE "quxes"."foo_id" = 1

这意味着除非关联的bar被持久化,否则bars关系的SQL将无法获取它:

> persisted_foo.quxes.first.build_bar
#<Bar id: nil>
> persisted_foo.bars
#<ActiveRecord::Associations::CollectionProxy []>
> persisted_foo.quxes.first.save!
> persisted_foo.reload
> persisted_foo.bars
#<ActiveRecord::Associations::CollectionProxy [#<Bar id: 1>]>