Rails:为什么has_one关联方法行为不一致?

时间:2013-10-26 20:40:04

标签: ruby-on-rails ruby activerecord associations has-one

has_one关联方法对我来说执行不一致,我不知道为什么。

选择两个相互关联的简单模型:

class Container < ActiveRecord::Base
  has_one: :super
end

class Super < ActiveRecord::Base
  belongs_to: :container
end

以下代码可以正常工作:

container = Container.create
 ...

container.build_super
 ...
 => #<Super id: nil, container_id: 1, content: nil, created_at: nil, updated_at: nil>

container.super
 => #<Super id: nil, container_id: 1, content: nil, created_at: nil, updated_at: nil>

当您在上面的代码中调用container.super时,它将返回新构建的Super类实例。

但是,以下代码不起作用:

Container.create
 ...
 => #<Container id: 1, created_at: "2013-10-26 20:31:26", updated_at: "2013-10-26 20:31:26">

Container.first.build_super
 ...
 => #<Super id: nil, container_id: 1, content: nil, created_at: nil, updated_at: nil>

Container.first.super
  Container Load (0.2ms)  SELECT "containers".* FROM "containers" ORDER BY "containers"."id" ASC LIMIT 1
  Super Load (0.1ms)  SELECT "supers".* FROM "supers" WHERE "supers"."container_id" = ? ORDER BY "supers"."id" ASC LIMIT 1  [["container_id", 1]]
 => nil

Container.first.super返回nil,因为它似乎在db中查找Super的实例。但是,该实例尚未提交。

但是当container == Container.first时,为什么container.super和Container.first.super不会产生相同的结果?

2 个答案:

答案 0 :(得分:2)

在第一个示例中,超级对象内置在内存中,并在从数据库重新加载时丢失(如第二个示例所示)。如果您要在第一个示例中执行container.reload.super从数据库加载它,则内存中的对象将丢失且为零。

旁注:将您的关联命名为“超级”是一个非常糟糕的主意。这是Ruby中的保留关键字,用于在子类覆盖它时调用父类的方法。

答案 1 :(得分:2)

Container.first.build_super获取Container记录的副本,构建关联实例,并将此关联实例缓存在Container记录的副本中。

在此之后调用Container.first.super获取Container记录的单独副本,并发现它没有:super的任何内容。

基本上,你这样做:

a = Container.first    # New instance
a.build_super          # Assign to :super

b = Container.first    # Separate instance
b.super                # Nothing in :super

您可能想要做的是将其分配给变量而不是获取另一个副本:

container = Container.first
container.build_super
container.super