はじめに
RailsでWebサービスを開発する際のDB設計では基本的にidが主キーになると思います。
ただし、複合主キーのテーブルを扱わなければならないケースも稀にあります(先日遭遇しました)ので、Railsで複合主キーのテーブルを扱う方法を紹介します。
前提条件
- Ruby (2.4.1)
- Rails (5.1.4)
- composite_primary_keys (10.0.2)
実装例
複合主キーのテーブルをActiveRecordで扱いやすくするために「composite_primary_keys」というGemを利用します。
https://github.com/composite-primary-keys/composite_primary_keys
config
config/environments/development.rbの末尾に以下の一行を追加します。
1 2 3 4 | Rails.application.configure do # 省略 require 'composite_primary_keys' end |
マイグレーション
childrenテーブルとparentsテーブルを例として実装を見ていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class CreateUsers < ActiveRecord::Migration[5.1] def change create_table :children, primary_key: %w(name school_year class_num) do |t| t.string :name, limit: 16, default: '', null: false t.integer :school_year, default: 1, null: false t.integer :class_num, default: 1, null: false t.integer :height t.integer :weight t.string :parent_name, limit: 16, default: '', null: false t.string :parent_address, limit: 255, default: '', null: false t.timestamps end create_table :parents, primary_key: %w(name address) do |t| t.string :name, limit: 16, default: '', null: false t.string :address, limit: 255, default: '', null: false t.timestamps end end end |
「primary_key: %w(name school_year class_num)」で主キーを指定している以外は普通のマイグレーションファイルだと思います。
この場合「id」のカラムは追加されません。
モデル
続いてモデルの実装を見ていきます。
1 2 3 4 | class Child < ApplicationRecord self.primary_keys = :name, :school_year, :class_num belongs_to :parent, foreign_key: [:parent_name, :parent_address] end |
1 2 3 4 | class Parent < ApplicationRecord self.primary_keys = :name, :address has_many :children, class_name: 'Child', foreign_key: [:parent_name, :parent_address] end |
上記の通り「self.primary_keys = :name, :school_year, :class_num」で主キーを指定してやる必要があります。
外部キーを指定してやることで「belongs_to」や「has_many」などもいつもどおり使えます。
「new」や「save」などもいつもどおり使えますが「find」は条件をカンマ区切りで指定してやる必要があります。
例
Child.find('Ichiro Yamada,1,1')
※検索条件に文字列が含まれる場合は全て文字列で記述します。
さいごに
実際のサービス開発では複合主キーは使わないほうがいいかもしれませんが、参考になれば幸いです。