0

has_many在模型上声明关系时,会动态添加访问器方法,允许传入 id 数组:

class Example < ActiveRecord::Base
   has_many :foos
end

这使得:

$ m = Example.create!
$ m.foo_ids = [1, 2, 3]

但是,当has_one声明关系时,会创建这样的访问器:

class Example < ActiveRecord::Base
   has_one :foo
end

不允许:

$ m = Example.create!
$ m.foo_id = 1 # No method error

为什么会出现这种差异?

为什么可以使用它们的 id 从一个表单中设置多个关联,但是要设置一个单一的关联,需要一个嵌套表单并且accepts_nested_attributes_for需要在模型上定义一个?这感觉就像 API 中的差异。

4

5 回答 5

1

这是因为几乎没有关联宏创建"{{association_name}}_id"访问器 - 它是ActiveRecord基于 DB 表中的列创建的。此外,has_one关联意味着关联模型具有外键列,因此如果您的关联与 DB 模式一致,则不应引发错误:

foo = Foo.new
foo.example_id
于 2013-10-22T10:49:03.327 回答
1

根据指南collection_singular_ids=(m.foo_ids=) 方法通过酌情添加和删除,使集合仅包含由提供的主键值标识的对象。这意味着它会将具有 ids [1, 2, 3] 的 foos 分配给示例 m。

现在他们有一个不同的方法collection=objects(m.foo=),它将接收 foo 对象的数组作为参数,并将这些 foo 与示例相关联。

最后,当我们使用has_one关联时,只能有一个对象与示例关联。所以我们不需要两种不同的方法来完成相同的工作,因此它们没有collection_singular_id=方法,因为它会令人困惑,但它们有association=(associate)方法来分配关联。

从指南:

Association= 方法将关联对象分配给该对象。在幕后,这意味着从该对象中提取主键并将关联对象的外键设置为相同的值。

于 2013-10-22T11:42:32.273 回答
1

对于 has_one,您应该使用单数而不是复数:

has_one :foo
于 2013-10-22T10:35:51.387 回答
0

为什么要为单个实例创建该访问器?无需将 ID 数组传递给它。访问器foo_id=将等同于foo.id=,那么为什么要创建它呢?

于 2013-10-22T10:59:33.653 回答
-2

对于动态生成的访问者,您应该在模型中使用 method_missing。

对于动态关联模型,请使用 polimirphic 关联。

于 2013-10-22T10:52:02.837 回答