はじめに
多対多の関係は、Webアプリケーションのデータモデリングで頻繁に遭遇するパターンの一つです。Rails では has_many :through
アソシエーションを利用して、この種の複雑な関連を簡単に扱うことができます。本記事では、service
と category
の多対多の関係を例に、Rails でのアプローチとSQLクエリの両方を通じて、データの効率的な取得方法を解説します。
モデルの設定
まず、service
、category
、service_category
の三つのモデルを設定します。以下のように各モデルに適切なアソシエーションを設定することから始めます。
# app/models/service.rb
class Service < ApplicationRecord
has_many :service_categories
has_many :categories, through: :service_categories
end
# app/models/category.rb
class Category < ApplicationRecord
has_many :service_categories
has_many :services, through: :service_categories
end
# app/models/service_category.rb
class ServiceCategory < ApplicationRecord
belongs_to :service
belongs_to :category
end
データの取得:ActiveRecordを使用したアプローチ
モデルが設定されたら、次にデータの取得方法を考えます。Railsの includes
メソッドを使用して、Service
のデータと関連する Category
のデータを効率的に取得する方法を見てみましょう。
# Service と関連する Category を取得
@services = Service.includes(:categories).all
このコードにより、@services
に含まれる各 service
オブジェクトから service.categories
を呼び出すことで、関連するカテゴリがすでにロードされているため、N+1問題を回避できます。
SQL クエリでのアプローチ
Railsの外でSQLを直接書く必要がある場合は、次のようにJOINを使用して関連するデータを取得します。
SELECT services.*, categories.*
FROM services
JOIN service_categories ON services.id = service_categories.service_id
JOIN categories ON service_categories.category_id = categories.id;
このクエリでは、services
テーブルと categories
テーブルを service_categories
を通じてJOINしているため、services
に関連する categories
の情報も一緒に取得できます。
まとめ
Railsでの開発ではActiveRecordを活用することで、複雑なデータ構造も簡単に扱うことができます。次回は、includesとjoinsの違いについて詳しく解説し、いつどちらを使うべきかを掘り下げます。興味がある方は、ぜひフォローしてください。
次回以降の記事