5
5

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.

Railsでアソシエーションされたモデルを条件にして検索する

Last updated at Posted at 2014-02-23

ブログを更新しました。元の記事はコチラ


ブログポストが複数カテゴリを持てるという場合で、
ある記事と同じカテゴリを持つ記事を探すということをやりたい。

Screen Shot 2014-02-23 at 9.34.23 AM


# Postモデル
class Post < ActiveRecord::Base
	has_and_belongs_to_many :categories
end

# 交差テーブル
class CategoriesPost < ActiveRecord::Base
end

# Categoryモデル
class Category < ActiveRecord::Base
	has_and_belongs_to_many :posts
end


post = Post.first
categories = Category.joins(:posts).where("posts.id = ?", post.id).select("categories.id")
category_ids = categories.map { |c| c.id }.join(',')

posts = Post.joins(:categories).where("categories.id IN (#{category_ids})").uniq

 
これで取り出せはするんだけど、カテゴリは複数持てる設定だから、INでやると当然記事は重複する。id=1の記事はカテゴリ13,33,36を持っているからid=1の記事を3回も取得してしまう。

uniqで重複は消してしまえるけど、もっとスマートな方法ないかな。
SQLに詳しい人教えてください。


references(*args)という便利なメソッドをnaotorさんから教えて頂きましたー。
Categoryのidは自分で集めなくてもpost.category_idsでいけるんですね。
いつかRailsチュートリアルで見た気がするな。

http://api.rubyonrails.orgから引用


User.includes(:posts).where("posts.name = 'foo'")
# => Doesn't JOIN the posts table, resulting in an error.

User.includes(:posts).where("posts.name = 'foo'").references(:posts)
# => Query now knows the string references posts, so adds a JOIN


post = Post.first
posts = Post.includes(:categories).where(categories_posts: {category_id: post.category_ids}).references(:categories)

http://workabroad.jp/posts/2060

5
5
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
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?