【Rails】references型とは何か?わかりやすく解説。外部キー(foreign_key)とは?belongs_toやhas_manyの意味と実例

rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。

RailsでDB操作をするための、モデルの生成時にreferences型(リファレンシズ型)を指定することがあります。

このreferences型をどういったときに使って、これをつけたことでどういう処理が行われるのかをまとめています。

また、関連性が深いbelongs_to, has_many, 外部キーについても解説しています。

references型とは?

references型は新しく作成するテーブルのカラムに、作成済みのテーブルを指定する場合に使います

既存のテーブルを参照するので、reference(参照という意味)と言います。

referencesの使い方

例えば、クライアント(clients)とプロジェクト(projects)という2つのテーブルを用意して、クライアント毎どのプロジェクトを進めているかを関連付けたいとします。

クライアントが複数のプロジェクトを同時進行できるとすると、1:多 の関係は、クライアントが1、プロジェクトが 多 となります。

このとき、各プロジェクトがどのクライアントに属しているかを指定するのが、references型です。


referencesを使う場所

referencesはrails g modelで、モデルとマイグレーションファイルを生成する時のカラムの型を指定するときに使います。

モデル名(小文字):referencesの形で指定します。

Projectモデルのカラムの一つを、clientテーブルと紐付けたい場合は、client:referencesとします。

# rails g model Project client:references pj_name:string price:integer order_date:date

Running via Spring preloader in process 90
      invoke  active_record
      create    db/migrate/20210717014553_create_projects.rb
      create    app/models/project.rb
      invoke    test_unit
      create      test/models/project_test.rb
      create      test/fixtures/projects.yml

モデル

referencesを指定したことで、生成されたモデルファイルに、belongs_to :client が追加されます。

class Project < ApplicationRecord
  belongs_to :client
end


belongs_toとは?(has_manyとの関係)

belongs_toとは、他のテーブルとの関係性を示すもので、自分のテーブルが指定したテーブルの下に紐づいている(属している)ことを示しています。

モデルの中で belongs_to :モデル名(小文字・単数形)として指定します。

一方で、親となるテーブルには、下に複数のテーブルが紐づくことを示すために、belongs_to :モデル名(小文字・複数形)を記述します。

referencesを使えば、belongs_toは自動で記述されますが、has_manyはつかないので、こちらは自分で記述する必要があります。

例:belongs_toとhas_manyの関係性


マイグレーションファイル

references型を指定して、rails g modelを実行するとモデルの他に、マイグレーションファイルにも特別な記述が入ります。

それが、t.referencesnull: falseforeign_key: true です。

t.references :テーブル名, null: false, foreign_key: true
  • t.references
    カラムが他のテーブルを参照していることを示します。
    カラム名は、指定したテーブルの前に id_ がつきます。(t.references :client であれば、カラム名は id_client になる)
  • null: false
    NULL値、つまり空欄を許可しないという指定です。
  • foreign_key: true
    外部キーであることを示しています。(※とても重要)

マイグレーションファイルの例

class CreateProjects < ActiveRecord::Migration[6.1]
  def change
    create_table :projects do |t|
      t.references :client, null: false, foreign_key: true
      t.string :pj_name
      t.integer :price
      t.date :order_date

      t.timestamps
    end
  end
end


外部キーとは?(foreign_keyとは)

外部キーとは、指定したカラムの自由な記述を許可せず、指定したカラムの値のみしか使えないようにする制限です。

指定するには、マイグレーションファイルで、対象のカラムのオプションとして、foreign_key: true を追記します。

例えば、次の場合は、clientsテーブルを外部キーとして指定するという意味になります。こうすることで、このカラムは、clientsテーブルの値しか選択できないように制限がかかります。

t.references :client, foreign_key: true



referencesの使い方実例

referencesの使い方の実例として、クライアントとプロジェクトを関連付けたテーブルを作成します。

クライアントが複数のプロジェクトを同時に持つ可能性があるテーブル構成にします。

クライアントテーブルの作成

まずは、「1:n」の「1」にあたるクライアントテーブルを作成します。

モデルとマイグレーションファイルの作成

モデル名をClientとし、client_nameカラムを作成するためのモデルとマイグレーションファイルを作成します。

rails g model client client_name:string



▼実行例

# rails g model client client_name:string
Running via Spring preloader in process 55
      invoke  active_record
      create    db/migrate/20210717013018_create_clients.rb
      create    app/models/client.rb
      invoke    test_unit
      create      test/models/client_test.rb
      create      test/fixtures/clients.yml

マイグレーションの実行

マイグレーションファイルが生成されたので、マイグレーションを実行します。これでDBにclientsテーブルが作成されます。

rails db:migrate



▼実例

# rails db:migrate
== 20210717013018 CreateClients: migrating ====================================
-- create_table(:clients)
   -> 0.0842s
== 20210717013018 CreateClients: migrated (0.0843s) ===========================


プロジェクトテーブルの作成

次に、「1:n」の「n」にあたるプロジェクトテーブルを作成します。

モデルとマイグレーションファイルの作成

モデル名をProjectとし、 先ほど作成したClientと対応させたclient_idと、pj_name, price, order_date の4つのカラムを作成するためのマイグレーションファイルを生成します。

rails g model Project client:references pj_name:string price:integer order_date:date


※注意: referencesを指定するのは、カラム名ではなくテーブル名です。

reference型とは?

reference型は他のテーブルを参照するときに使います。

reference型を指定したカラム名は テーブル名_id となります。(client:reference であれば、 client_id というカラムが生成されます)

  • 生成したモデルには、属することを示す belogns_to :テーブル名 が記載されます。
  • マイグレーションファイルには自由な編集を禁止する外部キー foreign_key: trueが設定されます。

生成されるモデル(app/models/project.rb)は次のようになります。関連性(リレーション)を示すbelongs_to が記述されています。

class Project < ApplicationRecord
  belongs_to :client
end

生成されるマイグレーションファイルは次のようになります。references型を指定したカラムに foreign_key: true が設定されています。

これで、クライアント名は外部から参照し、自由な追加・編集を許可しない設定になります。

class CreateProjects < ActiveRecord::Migration[6.1]
  def change
    create_table :projects do |t|
      t.references :client, null: false, foreign_key: true
      t.string :pj_name
      t.integer :price
      t.date :order_date

      t.timestamps
    end
  end
end


Clientモデルの編集

クライアントとプロジェクトの関係は、1:多 の関係になります。一人のクライアントが複数のプロジェクトを持つこともあります。

プロジェクトが一人のクライアントに属するという設定は、先ほどの、client:references によって、モデルファイルの中に、 belongs_to :client が記載されているので設定済みとなります。

一方で、クライアントが複数のプロジェクトを持つことがある(has_many :<テーブル名>)という関係性をClientモデルに追記する必要があります。

app/models/client.rb に以下を追記します。

class Client < ApplicationRecord
  has_many :projects
end
注意点
  • has_manyで指定するテーブル名は、複数形
  • belongs_toで指定するテーブル名は、単数形


マイグレーションの実行

マイグレーションを実行します。これでprojectsテーブルが生成されます。

rails db:migrate


以上で、クライアントとプロジェクトの2つのテーブルを関連づけることができました。


データベースの操作がとても簡単にできるRailsのActiveAdminというgem(ライブラリ)を使うと2つの関係性がよりわかりやすくなるので、よかったら試してみてください。

(参考)Docker上のRails6にActiveAdminを導入する方法(webpacker使用)と表示内容を変える方法

タイトルとURLをコピーしました