138

私はそれが何でhas_many :throughあり、いつそれを使用するか(そしてどのように)を理解しようとしています。しかし、私はそれを取得していません。Beginning Rails 3を読んでいて、グーグルを試しましたが、理解できません。

4

3 に答える 3

240

これらのモデルがあるとします。

Car
Engine
Piston

has_one :engine
エンジンbelongs_to :car
エンジンhas_many :pistons
ピストンbelongs_to :engine

車のhas_many :pistons, through: :engine
ピストンhas_one :car, through: :engine

基本的に、モデルの関係を別のモデルに委任しているので、を呼び出す代わりに、次のcar.engine.pistonsことを実行できます。car.pistons

于 2012-07-22T14:44:41.113 に答える
190

2つのモデルがあるとします: UserGroup

ユーザーをグループに所属させたい場合は、次のようにすることができます。

class Group < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :group
end

アソシエーションに関する追加のメタデータを追跡したい場合はどうなりますか?たとえば、ユーザーがグループに参加したとき、またはおそらくグループ内でのユーザーの役割は何ですか?

ここで、関連付けをファーストクラスオブジェクトにします。

class GroupMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :group

  # has attributes for date_joined and role
end

これにより、新しいテーブルが導入さgroup_idれ、ユーザーのテーブルから列が削除されます。

このコードの問題は、ユーザークラスを使用する他のすべての場所を更新して変更する必要があることです。

user.groups.first.name

# becomes

user.group_memberships.first.group.name

このタイプのコードはひどいものであり、このような変更を導入するのは面倒です。

has_many :through両方の長所を提供します。

class User < ActiveRecord::Base
  has_many :group_memberships
  has_many :groups, :through => :group_memberships  # Edit :needs to be plural same as the has_many relationship   
end

これで、通常のように扱うことができますがhas_many、必要なときにアソシエーションモデルのメリットを享受できます。

でこれを行うこともできることに注意してくださいhas_one

編集:ユーザーをグループに簡単に追加できるようにする

def add_group(group, role = "member")
  self.group_associations.build(:group => group, :role => role)
end
于 2012-07-22T14:47:22.737 に答える
21

ActiveRecord結合テーブル

has_many :throughリレーションシップは、他のテーブル間のリレーションシップを表す中間テーブルである結合テーブルhas_and_belongs_to_manyを介して機能します。JOINクエリとは異なり、データは実際にはテーブルに格納されます。

実用的な違い

を使用has_and_belongs_to_manyすると、主キーは不要であり、ActiveRecordモデルではなくActiveRecordリレーションを介してレコードにアクセスします。多対多の関係を持つ2つのモデルをリンクする場合は、通常、HABTMを使用します。

has_many :through主キーと結合データにカスタム列を追加する機能を備えたRailsモデルとして結合テーブルを操作する場合は、リレーションシップを使用します。後者は、結合された行に関連するが、実際には関連するモデルに属していないデータにとって特に重要です。たとえば、結合された行のフィールドから導出された計算値を格納します。

関連項目

アクティブレコードアソシエーションのガイド」の推奨事項は次のとおりです。

最も簡単な経験則は、関係モデルを独立したエンティティとして操作する必要がある場合は、has_many:through関係を設定する必要があるということです。リレーションシップモデルで何もする必要がない場合は、has_and_belongs_to_manyリレーションシップを設定する方が簡単な場合があります(ただし、データベースに結合テーブルを作成することを忘れないでください)。

結合モデルで検証、コールバック、または追加の属性が必要な場合は、has_many:throughを使用する必要があります。

于 2012-07-22T15:20:01.383 に答える