2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

has_many :through のNested Associations

Last updated at Posted at 2015-07-21

RailsTutorialで訳がわからんところがあったのでメモ

Chap 12 - Listing 12.8: Adding the User model following association.

app/models/relationship.rb

class Relationship < ActiveRecord::Base
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
end

ときて

app/models/user.rb

 class User < ActiveRecord::Base
  has_many :microposts, dependent: :destroy
  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :following, through: :active_relationships, source: :followed
  .
  .
  .
end

↑となるが。class Userの中はなぜ

  has_many :active_relationships, class_name: "Relationship",...
  has_many :following, through: :relationships, ...

↑じゃないのかなと。ていうかhas_manyで事前に定義したAssocって使えるの?なんで?

ActiveRecord::Associations::ClassMethods


activerecord/lib/active_record/associations.rb
をみると。

##Nested Associations
You can actually specify any association with the :through option, including an association which has a :through option itself.

Throughに入れるAssociationはなに使ってもいいお。(^ω^ ≡ ^ω^)

ということだそうで。

以下2つは同じことらしい


class Author < ActiveRecord::Base
  has_many :posts
  has_many :comments, through: :posts
  has_many :commenters, through: :comments
end

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :commenter
end

@author = Author.first
@author.commenters # => People who commented on posts written by the author
class Author < ActiveRecord::Base
  has_many :posts
  has_many :commenters, through: :posts
end

class Post < ActiveRecord::Base
  has_many :comments
  has_many :commenters, through: :comments
end

class Comment < ActiveRecord::Base
  belongs_to :commenter
end

じゃあ書きなおしてみる

ソースコードとか読んでみたけどいまいちよくわからんし。
pryでちまちまプロセスを追ってみたけどヒントにもならず。
ソースの仕組みを書いたブログもあったけどそれでもよくわからない。
とりあえずこのあたりは「こういうふうに動く」と覚えとくかなー

app/models/user.rb
class User < ActiveRecord::Base
  has_many :microposts, dependent: :destroy
  
  #チュートリアルのやりかた
  has_many :active_relationships, class_name: "Relationship",
    foreign_key: "follower_id", dependent: :destroy
  has_many :followings, through: :active_relationships, source: :followed

  #書き換え1
  #relationships が class Relationshipと同じ名前
  # class_name で「これはエイリアス」と言ってやらなくて良い
  has_many :relationships, foreign_key: "follower_id"
  has_many :followings1, through: :relationships, source: :followed

  #書き換え2
  #ひとつ目はfollower なのに foreign_key: follower_idを指定しないと動かない
  #2つ目はfollowed とfollowed_idと同じ名前なのでsource:でidを指定しなくて良い。
  has_many :follower, class_name: "Relationship", foreign_key: "follower_id"
  has_many :followed, through: :follower
end

基本形が

has_many :(ジョインテーブル名)
has_many :(ジョインの先のテーブル名) through: :(ジョインテーブル名)

だから

要するにこういうことなんだろうなぁと。

  has_many :relationships, (class_name: "Relationship",) foreign_key: "follower_id"
  has_many :followed, through: :relationships, (source: :followed)

関連記事

[Nested Associations and Has_many :through, :source]
(http://ryandeussing.com/blog/2013/06/12/nested-associations-and-has-many-through/)
=> has many throughってこう使うんだよ。的な記事。

[Ruby on Rails] ActiveRecord の歩き方
=> 古い記事。掲載されてるソースコードは実際のとかなり違うので注意。
  1から4まである。

[Under the hoods of ActiveRecord’s has_many method]
(http://depthcoding.ybarthelemy.info/2012/07/30/under-the-hoods-of-activerecords-has_many-method/)
=> 三年前の記事

[Behind the Scenes of the ‘Has Many’ Active Record Association]
(http://callahanchris.github.io/blog/2014/10/08/behind-the-scenes-of-the-has-many-active-record-association/)
=> 日付がないのでいつのかわからないが、Github上の一番新しい奴に近い時点のコードを使ってると思われる。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?