中間テーブルを用いた多対多の関係(その 5)
前回からの続きです。モデル同士のアソシエーションを定義します。
class Customer < ActiveRecord::Base has_many :sales has_many :products, :through => :sales end
class Product < ActiveRecord::Base has_many :sales end
class Employee < ActiveRecord::Base has_and_belongs_to_many :branches belongs_to :manager, :class_name => 'Employee', :foreign_key => 'mgr_id' has_many :assistants, :class_name => 'Employee', :foreign_key => 'mgr_id' has_many :sales scope :belongs, lambda { |b| joins(:branches).where(:branches => { :name => b }) } end
class Branch < ActiveRecord::Base has_and_belongs_to_many :employees end
class Sale < ActiveRecord::Base belongs_to :product belongs_to :employee belongs_to :customer end
中間テーブルの話からは逸れますが、Employee
クラスを見ていただいてわかるとおり、アソシエーションはテーブル名と一致しないものも作れます。その場合は対応するモデルと結合に利用する外部キーを指定する必要があります。
Employee
と Branch
の関係は以前にやったのと同じ、外部キーしか持たない中間テーブルを利用した多対多の関係です。
注目すべきは Customer
と Product
の関係です。Customer
と Sale
は一対多の関係にありますが、Product
と Sale
が一対多の関係にあることを利用して Customer
と Product
の多対多の関係を持たせています。その場合は has_many
を使いますが
has_many :products, :through => :sales
のように経由する中間テーブルを指定する必要があります。また、中間テーブルのデータとなるモデルに対するアソシエーションも併せて定義しておく必要があります。
実際の利用例です。
app/controllers/customer_controller.rb
class CustomersController < ApplicationController ... def show @customer = Customer.find(params[:id]) end ... end
app/views/customers/show.html.erb
... <h2>購入した商品</h2> <ul> <% @customer.products.uniq.each do |p| %> <li><%= p.name %></li> <% end %> </ul> ...
出力例は次回に。