has_one的用途是什么:通过这里(来自Rails指南的例子)

时间:2010-05-26 10:25:19

标签: ruby-on-rails associations

Example screenshot http://guides.rubyonrails.org/images/has_one_through.png

为什么他们使用has_one:通过这里。我们只能用has_one做同样的事情。什么是创建一个新课程的需要。你能给我一些好的例子吗?

以下是原始示例的链接 from Rails guide

修改

我们可以通过这种方式做同样的事情,使它成为一个has_one:通过

  class Supplier < ActiveRecord::Base
     has_one :account  
  end

  class Account < ActiveRecord::Base 
    belongs_to :supplier    // add a another column credit_rating in accounts table
  end

4 个答案:

答案 0 :(得分:2)

正在使用has_one :through关联,因为联接模型(AccountHistory)包含与SupplierAccount之间的关联相关的其他信息,即信用评级。

Rails指南中的这个示例选择得很差,因为使用has_one :through比使用has_one credit_rating属性Account更好的原因并不明显模型。

当您需要连接模型上的额外属性时,您应该使用has_one :throughhas_many :through关联,这些属性在逻辑上不属于构成关联的其他模型。一个典型的例子是将图书借给图书馆内的用户。图书借阅的日期和持续时间属于(贷款)连接模型,因为从逻辑上讲,它们不是属于用户或图书的属性。在这种情况下,使用has_many :through关联是合适的。

答案 1 :(得分:1)

因为使用has_one :through,您可以向Account

添加更多属性

答案 2 :(得分:1)

在某些情况下,您可能不希望向表中添加特定字段。在您的示例中,您实际上只需要一个表,因为您可以将account_numbercredit_ranking添加到suppliers表中。但有时将数据存储在多个表中是个好主意。然后你必须使用has_one(一对一)关系。

在您的示例中,您还可以将属性supplier_id添加到account_histories,并将has_one :account_history, :through account替换为has_one :account_history,但这将是多余的,并且会使您的代码复杂化需要确保你不改变一个属性而忘记更新另一个属性。

<强>更新

如果您未将supplier_id属性添加到account_histories,则Rails将无法确定该表中的哪一行属于哪个供应商。找到它的唯一方法是查看相关的accounts表。没有accounts,您无法确定哪个account_history属于供应商,因为accounts_histories表没有suppliers表的任何外键。

要获得没有account_history选项的供应商的:through,您必须执行此操作:

Supplier.find(id).account.account_history

:through允许您将其替换为:

Supplier.find(id).account_history

正如您在更新中所写的那样,您可以将credit_ranking属性添加到accounts并且只有两个表。这将更加简单,但您可能不希望将该属性存储在同一个表中(因为您可能已经拥有许多其他属性,并且不想添加更多属性)。

答案 3 :(得分:1)

我认为在这种情况下,它取决于您如何设计数据库模型。 Rails的优点是,如果你使用一些遗留数据库,它可以处理几乎所有的关系类型。在这种情况下,您将使用:has_one:through,因为您的数据库表是以这种方式建模的。

建议使用三种模型的优点:帐户和AccountHistory之间存在清晰的分离。虽然您可以将Account和AccountHistory建模为一个组合模型,但是没有必要。 在这么小的例子中,这似乎没有用,但是例如:

  • 假设AccountHistory附加了大量日志记录,以便能够计算某个帐户是否仍然值得信赖(或其他);在此设置中,两个模型不必同时加载:您现在只能使用Account或AccountHistory
  • 与任何一个模型(历史与否)的代码现在是分开的,使你的模型的意图更清洁