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.references
、null: false
、 foreign_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を指定するのは、カラム名ではなくテーブル名です。
生成されるモデル(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
マイグレーションの実行
マイグレーションを実行します。これでprojectsテーブルが生成されます。
rails db:migrate
以上で、クライアントとプロジェクトの2つのテーブルを関連づけることができました。
データベースの操作がとても簡単にできるRailsのActiveAdminというgem(ライブラリ)を使うと2つの関係性がよりわかりやすくなるので、よかったら試してみてください。
(参考)Docker上のRails6にActiveAdminを導入する方法(webpacker使用)と表示内容を変える方法