Rails has_one:通过关联


69

Rails的has_one :through关联可以通过第二种模型来帮助与第三种模型建立一对一的关联。除了建立快捷方式关联之外,该功能的真正用途是什么,否则还有一步之遥。

从Rails指南中获取以下示例:

class Supplier < ActiveRecord::Base
  has_one :account
  has_one :account_history, :through => :account
end

class Account < ActiveRecord::Base
  belongs_to :supplier
  has_one :account_history
end

class AccountHistory < ActiveRecord::Base
  belongs_to :account
end

可能会让我们做类似的事情:

supplier.account_history

否则将达到:

supplier.account.history

如果仅是为了更简单的访问,那么从技术上讲,可能存在一对一关联,该关联将一个模型与经过n-1个模型的第n个模型连接起来,以便于访问。除了快捷方式,我还有什么想念的吗?


非常感谢。我已经苦苦挣扎了几天,试图在不知道需要:through指令的情况下使其正常工作。现在一切都好了。
ed_is_my_name

Answers:


56
  1. 逻辑,好吧,这听起来可能有点弱,但是说“我有一个与我有一个帐户的供应商,我想查看该供应商的整个帐户历史”是合乎逻辑的,所以对我来说很有意义以便能够直接从供应商访问帐户历史记录。

  2. 效率,对我来说,这是我要使用的主要原因:through,仅因为此命令发出了一个join语句,而不是先调用供应商,然后是account,然后是account_history。注意到数据库调用数量了吗?

    • 使用:through,1个调用以获取供应商,1个调用获取account_history(rails自动用于:join通过帐户进行检索)

    • 使用普通关联,1个致电获取供应商,1个致电获取帐户和1个致电获取account_history

我认为这就是=)希望能有所帮助!


2
我认为逻辑论证是非常有效的。听起来更自然,让我了解此供应商的帐户历史记录,而不是供应商的帐户历史记录。考虑到Ruby / Rails的流畅句子而不是代码的哲学,这非常微妙,但仍然容易记住。我知道我们可以看到实际发出的数据库查询,但是Rails是否指定这些方法调用将如何转换为SQL?
阿努拉格

10
这也避免了违反得墨meter耳定律。
汤姆·克雷福德

2
@TomCrayford,我真的不知道它是怎么做的。这是否会使关系不那么直接?
贾斯珀·肯尼斯

1
@JasperKennis的物理关系不太直接,但是假设其他不直接链接表的原因(例如,将provider_id从account规范化为account_history要求回调和少量存储空间的事实),这使您不必每次您通过供应商访问帐户历史记录时,都不必编写一系列方法。而且,如果稍后之间的表发生更改,则无需在整个应用程序中重写方法调用。您只需要更改关联。
莫里斯·2015年

我们也不要忘记避免这样的情况:您可能需要从一个类中调用另一个类方法以进行非常简单的操作,并且不想为可能是一个非常简单的数据请求创建接口或服务对象。has_one :through与在调用类中注入或实例化第三类相比,在第三级关系数据上执行操作要干净得多。
托德

11
  • 逆关联:考虑经典情况下的用户-成员-组。如果用户可以是许多组中的成员,则一个组中有许多成员或用户,而用户中有许多组。但是,如果用户只能是一个组中的成员,则该组仍然有许多成员:class User has_one :group, :through => :membership但是class Group has_many :members, :through => memberships。中间模型membership对于跟踪逆关系很有用。

  • 可扩展性has_one :through可以很容易地将关系扩展和扩展为has_many :through关系


11

我很惊讶没有人接触过关联对象

一个has_many(或has_one:through关系有助于使用关联对象模式,即当您有两个相互关联的事物,并且该关联本身具有属性(即,建立关联的日期或何时终止)。

某些人认为这是has_and_belongs_to_manyActiveRecord助手的很好的选择。其背后的原因是很有可能您需要更改关联的性质或将其添加,并且当您进入一个项目几个月后,如果最初将关系建立为一个has_and_belongs_to_many(第二个链接会详细介绍)。如果最初是使用has_many :through关系建立的,那么在项目开始几个月后,就很容易重命名联接模型或向其添加属性,从而使开发人员更容易响应不断变化的需求。计划变更。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.