関連付けとは
Railsでは、モデルやテーブル同士の関係を設定することができます。
例えばUserモデルとTaskモデルの関係などを定義します。
(この場合、1人のユーザーが複数のタスクを持っている)
何がうれしいのか
必要な記述が少なく、シンプルになります。
TODOアプリを例に説明すると、以下のように記述が簡素化します。
タスク作成時
Task.create(title: "パンを買う", user_id: @user.id)
↓
@user.tasks.create(title: "パンを買う")
ユーザー削除時
@tasks = Task.where(user_id: @user.id)
@tasks.each do |task|
task.destroy
end
@user.destroy
↓
@user.destroy
その他、以下のようなメソッドが使えるようになります。
メソッド | 用途 |
---|---|
task.user | タスクに紐付いたUserオブジェクトを返す |
user.tasks | Userのタスクの集合を返す |
user.tasks.build(arg) | userに紐付いた新しいTaskオブジェクトを返す |
user.tasks.find_by(id: 1) | userに紐付いていて、idが1であるタスクを検索する |
実装してみる
簡単なTODOアプリを例に、UserモデルとTaskモデルの関連付けをします。
Ruby on Railsで簡単なアプリを作成
【Rails】ログイン機能を実装する
tasksテーブルにuser_id
を追加
$ rails g migration Addカラム名Toテーブル名 カラム名:データ型
でカラムを追加するマイグレーションファイルを作成できます。
$ rails g migration AddUserToTasks user:references
作成されるファイル
class AddUserToTasks < ActiveRecord::Migration[5.1]
def change
add_reference :tasks, :user, foreign_key: true
end
end
ここでは外部キー制約を持ったreference型
のuser_id
というカラムを追加し、user_id
にはusersテーブルのidカラム
に入っているデータだけを許可します。
(データベース上には、usersテーブルのidカラムの型であるinteger型
として登録されます。)
外部キー (foreign key)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
$ rails db:migrate
has_many
、belongs_to
で関連付け
Taskモデルにbelongs_to
、Userモデルにhas_many
を記述し、関連付けを行います。
その他default_scope
で取り出す時の順番を指定したり、dependent: :destroy
でユーザーが削除された時にそのユーザーの持つタスクを全て削除するように設定できます。
class Task < ApplicationRecord
belongs_to :user
.
.
end
class User < ApplicationRecord
has_many :tasks, dependent: :destroy
.
.
end
タスク登録処理を修正
これまでTask.new
で取得していたタスクオブジェクトをcurrent_user.tasks.build
で書き換えます。
(このアプリではcurrent_userという関数で現在ログイン中のユーザーオブジェクトを返すことができます。)
.
.
def create
# @task = Task.new(task_params)
@task = current_user.tasks.build(task_params)
if @task.save
flash[:success] = "タスクを追加しました。"
.
.
まだこのアプリにはユーザー削除の機能がないので、削除時の動作の実装は割愛しますが、@user.destroy
でユーザーに紐づいた全てのタスクを削除できます。
外部キーを設定したカラムにnullを許可したい
optional: true
を指定すると、nullを許可できます。
belongs_to :user, optional: true
その他
外部キーを含むテーブルを作成する際には
$ rail g model user:references ...
$ rail g migration user:references ...
などで作ることが出来ます。
モデルを作った場合には、デフォルトでbelongs_to :user
が付与されます。