中間テーブルを用いた多対多の関係(その 1)
今「一人の従業員が複数(0 個も含む)の資格を持っている」「ある資格を持っている従業員が複数(0 人も含む)いる」という状況を考えます。これは多対多の関係ですが、RDBMS では多対多の関係をそのまま表現することができないので中間テーブルを用います。まずは関連モデルと中間テーブル作成からやっていきましょう。
rails g model employee name:string age:integer salary:integer sex_id:integer --timestamps=false rails g model sex name:string --timestamps=false rails g model license name:string --timestamps=false rails g migration CreateEmployeesLicenses employee_id:integer license_id:integer
できたマイグレーションファイル(xxxxxxxxxxxxxx_create_employees_licenses.rb)を編集します*1。
class CreateEmployeesLicenses < ActiveRecord::Migration def change create_table :employees_licenses, :id => false do |t| t.references :employee t.references :license end end end
今回作成する中間テーブルは外部キー以外を持たない(主キーも持たない !)ようにしたいので
:id => false
のオプションを付けます。
次にデータを挿入します。モデルがあるものは seeds.rb を利用して挿入します。
# (略) Sex.create( :name => '男性' ) Sex.create( :name => '女性' ) Sex.create( :name => 'その他' ) License.create( :name => '普通自動車第1種免許' ) License.create( :name => '英語検定1級' ) License.create( :name => '中国語検定1級' ) License.create( :name => '簿記' ) License.create( :name => '調理師' ) License.create( :name => '国内旅行取り扱い主任者' ) License.create( :name => '中小企業診断士' ) Employee.create( :name => '田中健太郎', :age => 27, :salary => 198000, :sex_id => 1 ) Employee.create( :name => '島田麻紀', :age => 23, :salary => 172000, :sex_id => 2 ) Employee.create( :name => '福井肇', :age => 32, :salary => 220000, :sex_id => 1 ) Employee.create( :name => '山本加奈子', :age => 33, :salary => 210000, :sex_id => 2 ) Employee.create( :name => '遠藤隆', :age => 45, :salary => 370000, :sex_id => 1 ) Employee.create( :name => '佐藤龍', :age => 52, :salary => 440000, :sex_id => 1 ) Employee.create( :name => '岩隈優', :age => 28, :salary => 270000, :sex_id => 2 ) Employee.create( :name => '本間佳子', :age => 29, :salary => 250000, :sex_id => 2 ) Employee.create( :name => '中田和良', :age => 55, :salary => 470000, :sex_id => 1 ) Employee.create( :name => '吉本一郎', :age => 48, :salary => 270000, :sex_id => 1 )
中間テーブルのデータは対応するモデルが無いので SQL 文を直接発行します。
INSERT INTO employees_licenses(employee_id, license_id) VALUES(1,1); INSERT INTO employees_licenses(employee_id, license_id) VALUES(1,2); INSERT INTO employees_licenses(employee_id, license_id) VALUES(1,4); INSERT INTO employees_licenses(employee_id, license_id) VALUES(2,2); INSERT INTO employees_licenses(employee_id, license_id) VALUES(3,1); INSERT INTO employees_licenses(employee_id, license_id) VALUES(3,4); INSERT INTO employees_licenses(employee_id, license_id) VALUES(7,1); INSERT INTO employees_licenses(employee_id, license_id) VALUES(8,5); INSERT INTO employees_licenses(employee_id, license_id) VALUES(9,1); INSERT INTO employees_licenses(employee_id, license_id) VALUES(9,7);
モデルにアソシエーションを定義します。
class Employee < ActiveRecord::Base has_and_belongs_to_many :licenses belongs_to :sex end
class License < ActiveRecord::Base has_and_belongs_to_many :employees end
class Sex < ActiveRecord::Base has_many :employees end
has_and_belongs_to_many
メソッドを利用して、中間テーブルを通して多対多の関係を表現します。
実際の利用例は次回以降に。