カテゴリー: BackEnd

Railsで複合主キーのテーブルを扱う

はじめに

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の末尾に以下の一行を追加します。

Rails.application.configure do
  # 省略
  require 'composite_primary_keys'
end

マイグレーション

childrenテーブルとparentsテーブルを例として実装を見ていきます。

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」のカラムは追加されません。

モデル

続いてモデルの実装を見ていきます。

class Child < ApplicationRecord
  self.primary_keys = :name, :school_year, :class_num
  belongs_to :parent, foreign_key: [:parent_name, :parent_address]
end
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')
※検索条件に文字列が含まれる場合は全て文字列で記述します。

さいごに

実際のサービス開発では複合主キーは使わないほうがいいかもしれませんが、参考になれば幸いです。

Hiroki Ono

シェア
執筆者:
Hiroki Ono
タグ: Rails

最近の投稿

フロントエンドで動画デコレーション&レンダリング

はじめに 今回は、以下のように…

4週間 前

Goのクエリビルダー goqu を使ってみる

はじめに 最近携わっているとあ…

1か月 前

【Xcode15】プライバシーマニフェスト対応に備えて

はじめに こんにちは、suzu…

2か月 前

FSMを使った状態管理をGoで実装する

はじめに 一般的なアプリケーシ…

3か月 前