【问题标题】:Do has_many :through associations work for models that only exist in memory?has_many :through 关联是否适用于仅存在于内存中的模型?
【发布时间】:2010-10-01 20:04:31
【问题描述】:

class A < ActiveRecord::Base
  has_many :bs
  has_many :cs, :through => :bs
end

class B < ActiveRecord::Base
  belongs_to :a
  belongs_to :c
end

class C < ActiveRecord::Base
  has_many :bs
end

如果我打开一个 Rails 控制台,然后做

a = A.new
b = a.bs.build
b.c = C.new

然后我得到

a.cs => []

但是

a.bs[0].c => c

如果 a 被保存,那么一切正常。这是预期的吗?当模型仅存在于内存中时,为什么通过关联不起作用?谢谢

【问题讨论】:

  • 也许,当对象被保存(或加载)而不是创建时,关联是“建立的”。您是否必须使用未保存的实例进行操作?
  • 不是,但我更喜欢在运行测试时占用尽可能小的内存,如果它们可以在内存中运行,我会节省很多时间。

标签: ruby-on-rails activerecord associations


【解决方案1】:

我猜想a 对象没有引用创建的对象c。通常它会运行一个查询,但它不会,因为它没有保存到数据库中。我认为它是为数据库关系创建的,它只是不检查对内存对象的引用。

你也可以试试这个:

a = A.new
a.cs.build
a.bs
=> []

但是

a.cs
=> [created c object]

【讨论】:

  • ActiveRecord 将模型和持久性交织在一起的另一个可悲的副作用。 Rails 和 AR 让我大部分时间都很开心,但现在我很伤心。 :(
【解决方案2】:

我是这样解决这个问题的:

class A < ActiveRecord::Base
  has_many :bs

  def cs
    bs.map &:c
  end

end

你可能会失去一些东西。例如,cs 现在是只读的,因此您不能分配给它或buildcreate。在我的特殊情况下这很好,因为我总是只会改变bs,这可能是一个更好的做法。此外,像B 这样的多对多对象通常会有一些您想要设置的属性。

顺便说一句,如果C 通过has_many 而不是belongs_to 连接到B,请将上面的代码更改为使用flat_map 而不是map

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多