Hack Your Design!

【Rails】has_many, throughの逆の関連はdelegate, toかhas_one, through

TL;DR

結論はbelongs_to,throughでなく、delegate, to もしくは has_one, through

has_many, through

RailsでこんなModel構成があったとします。ユーザーは複数の記事をもっていて、その記事は複数のタグを持っている、という状態です。

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  has_many :tags
  belongs_to :user
end

class Tag < ActiveRecord::Base
  belongs_to :post
end

特定のUserがどんなTagを持っているかを調べるにはthroughを使うと簡単に実装できます。Userモデルにthroughを追加しましょう。

class User < ActiveRecord::Base
  has_many :posts
  has_many :tags, through: :posts
end

class Post < ActiveRecord::Base
  has_many :tags
  belongs_to :user
end

class Tag < ActiveRecord::Base
  belongs_to :post
end

こうすることで、@user.tagsでユーザーが所有するタグを取得できます。

ではここで疑問。逆にTagからPostを省いてUserを導きだすことはできないのでしょうか?

1. delegate を使う

結論からいうとdelegateを利用することで省けます。具体的にはTagモデルをこうします。

class User < ActiveRecord::Base
  has_many :posts
  has_many :tags, through: :posts
end

class Post < ActiveRecord::Base
  has_many :tags
  belongs_to :user
end

class Tag < ActiveRecord::Base
  belongs_to :post
  delegate :user, to: :post
end

これで@tag.userなんて風に当該tagを所有するuserにアクセスできます。

2. has_one, through を使う

このようにhas_one, throughも使えます。

class User < ActiveRecord::Base
  has_many :posts
  has_many :tags, through: :posts
end

class Post < ActiveRecord::Base
  has_many :tags
  belongs_to :user
end

class Tag < ActiveRecord::Base
  belongs_to :post
  has_one :user, through: :post
end

参考

  • このエントリーをはてなブックマークに追加
comments powered by Disqus