ActiveRecord#joinsメソッド覚えました
Rails4
joinsメソッドを最近覚えました。
ActiveRecord#joinsとは、複数のテーブルを結合するメソッドです。
テーブルを跨いでレコードの抽出をしたい時に使います。
whereでin句を使えば、テーブル結合しなくても同じ結果が得られるのですがコードが冗長になると思います。(後述)
joinsメソッドを使った例は、ぺろぺろあんてなで使ったコードで説明してきます。
このアンテナサイト では、メインコンテンツ部に『サイトカテゴリ毎の二日分記事』を表示しております。
http://prpr-antena.com/adult であれば、アダルトカテゴリに属するサイトの記事を表示し、
http://prpr-antena.com/vipであれば、VIPカテゴリに属するサイトの記事を表示しています。
まずモデルの関連
モデルの関連は以下ようになっています。
記事はサイトに属していて、サイトはカテゴリに属しています。
class Post < ActiveRecord::Base belongs_to :site
class Site < ActiveRecord::Base has_many :posts belongs_to :category end
class Category < ActiveRecord::Base has_many :sites
[Post]*--[Site]*--[Category]
コントローラー
メインコンテンツ部に表示する記事は、”カテゴリ”で抽出したいのですが、
Postモデルだけでは、自身がどのサイトカテゴリに属しているかわかりません。
ということは、postsテーブルとsitesテーブルを結合する必要があります。
ちなみに、パラメータにはcategoriesテーブルのidが渡ってきます。
sitesテーブルが持っているcategoryの外部キーを使っても目標達成することはできるので、
categoriesテーブルとの結合は必須ではないのですが、今回は一緒に結合してみました。
以下のようになります。
Post.joins(site: :category).where("categories.id = ?", 2)
postsテーブルとsitesテーブルに結合したsitesテーブルにcategoriesテーブルを結合しています。
SELECT "posts".* FROM "posts" INNER JOIN "sites" ON "sites"."id" = "posts"."site_id" INNER JOIN "categories" ON "categories"."id" = "sites"."category_id" WHERE (categories.id = 2)
joinsメソッド使ってないのと比較してみる
使ってない
@category = Category.find(params[:id]) ids = @category.sites.pluck(:id) @posts = Post.where("site_id in (?)", ids). where("posts.created_at >= ?", DateTime.now - 2.day). order("created_at DESC")
使った
@category = Category.find(params[:id]) @posts = Post.joins(site: :category).where("categories.id = ?", @category). where("posts.created_at >= ?", DateTime.now - 2.day). order("created_at DESC")
DBへの問い合わせが1回減りました。
ActiveRecord#joinsメソッド覚えました。
http://guides.rubyonrails.org/active_record_querying.html