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不会产生相同的结果?
答案 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