web-dev-qa-db-ja.com

Rails has_one:through association

Railsにはhas_one :through関連付け。2番目のモデルを介して、3番目のモデルとの1対1の関連付けを設定できます。ショートカットアソシエーションを作成することに加えて、それが実際にどのように使用されるのか、それ以外の場合は余分なステップになります。

Rails guide

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番目のモデルを接続する1対1の関連付けがあり、アクセスが容易になります。ショートカット以外に不足しているものはありますか?

64
Anurag
  1. 論理、これは少し弱いかもしれませんが、「アカウントを持っているサプライヤーがいます。このサプライヤーのアカウント履歴全体を表示したい」と言うのは論理的です、したがって、サプライヤーから直接アカウント履歴にアクセスできるのは理にかなっています。

  2. 効率、これが私が:throughを使用する主な理由です。これは、サプライヤー、アカウント、およびaccount_historyを呼び出すのではなく、単に結合ステートメントを発行するからです。データベース呼び出しの数に気付きましたか?

    • :throughを使用して、サプライヤーを取得するための1回の呼び出し、account_historyを取得するための1回の呼び出し(Railsは自動的に:joinを使用してアカウントから取得します)

    • 通常の関連付けを使用して、サプライヤーを取得するための1回の呼び出し、アカウントを取得するための1回の呼び出し、およびaccount_historyを取得するための1回の呼び出し

それが私が思うことです=)それが役立つことを願っています!

51
Staelen

Association Objectsに誰も触れていないことに驚いています。

has_many(またはhas_one:through関係は、association object patternの使用を容易にします。相互に関連する2つのものがあり、そのリレーション自体に属性(関連付けが行われた日付または期限が切れた日付)があります。

これは some によって考慮され、has_and_belongs_to_many ActiveRecordヘルパーの優れた代替手段となります。この背後にある理由は、関連付けの性質を変更したり追加したりする必要がある可能性が非常に高いことであり、プロジェクトに数か月かかったときに、関係が最初に設定された場合、これは非常に痛いことがありますhas_and_belongs_to_many(2番目のリンクは詳細になります)。最初にhas_many :through関係を使用してセットアップされた場合、プロジェクトの数か月後に、結合モデルの名前変更や属性の追加が簡単になり、開発者が要件の変化に簡単に対応できるようになります。変更を計画します。

10
ryan0
  • 逆関連付け:古典的な状況user-membership-groupを考慮します。ユーザーが多くのグループのメンバーになることができる場合、グループには多くのメンバーまたはユーザーがあり、ユーザーには多くのグループがあります。ただし、ユーザーが1つのグループのメンバーにしかなれない場合、グループにはまだ多くのメンバーがあります:class User has_one :group, :through => :membershipしかしclass Group has_many :members, :through => memberships。中間モデルmembershipは、逆の関係を追跡するのに役立ちます。

  • 拡張性has_one :through関係は、has_many :through 関係

9
0x4a6f4672