LoginSignup
14
12

More than 5 years have passed since last update.

referencesを使った外部キー制約があるカラムの作成方法(Rails)

Posted at

はじめに

Rails チュートリアルなどで、Railsの勉強をしていて、Twitterでいう、ツイート機能を作成する際、UserモデルやTweetモデルなどのマイグレーションファイルの作成をしていた時に、UserモデルとTweetモデルを関連させたいモデルがあった時などに使う、外部キーのカラムの追加に関して調べていたら勉強になったので、まとめておきます。

環境

この記事では以下の環境(2018年6月19日時点)で動作確認できました。

  • Ruby: 2.4.1
  • Rails: 5.0.7

前提

お題「お気に入り機能を作成したい」と思った時、現状、ユーザー情報があるusersテーブルと、tweetのようなデータを扱うmicropostsテーブルを関連づけて、お気に入り機能を作りたいと思ったとを仮定します。

テーブル名同士の関係としては、お気に入り機能なので、users : microposts = 多 : 多の関係にしたいとします。モデル同士が多対多の関係になる場合には、中間テーブルを設置するのが有効な方法です。

中間テーブルとは

中間テーブルとは、usersmicropostsの関係を接続するテーブルです。例えば、Userが特定のMicropostをお気に入りする場合、usersテーブルの id とmicropostsテーブルのidを接続するテーブルを作成します。その接続するテーブル(例:likesテーブル)にはuser_idmicropost_idを設置します。 そのテーブルのレコードにuser_idが1で、micropost_idが2のものがあったとすると、idが 1のUserがidが10のMicropostを好き、ということを意味します。

そんな関係の中間テーブルを作るために、まず、reference型を使ってモデルを作成していきましょう。

モデル作成

users : microposts = 多 : 多の関係になるような中間テーブルである(Likeモデル)を作りたいとします。

$ rails g model Like user:references micropost:references

Running via Spring preloader in process 4905
      invoke  active_record
      create    db/migrate/20180619073616_create_likes.rb
      create    app/models/like.rb

今回はログイン済みユーザー(user_idをもつユーザー)でないとコメントできないようにするためにreferencesでモデルを生成をしました。

また、Likeモデルはユーザーと投稿内容の両方が存在しなければいけないのでバリデーションも設けます。

app/models/like.rb
class Like < ApplicationRecord
  belongs_to :user
  belongs_to :micropost

  validates :user_id, presence: true
  validates :micropost_id, presence: true
end

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

rails g modelコマンドによって、下記のマイグレーションファイルが作成されました。

20180619073616_create_likes.rb
class CreateLikes < ActiveRecord::Migration[5.0]
  def change
    create_table :likes do |t|
      t.references :user, foreign_key: true
      t.references :micropost, foreign_key: true

      t.timestamps
    end
  end
end
  • t.references :user, foreign_key: true
    • 実際のデータベース上では、user_idカラムとして存在しています
  • t.references :micropost, foreign_key: true
    • 実際のデータベース上では、micropost_idカラムとして存在しています

foreign_keyは外部キー制約というもので、保存されるテーブルの整合性を高め、間違ったデータをできるだけ排除できるかという性質があります。

マイグレーションの実行

マイグレーションの実行をすることでテーブルを作成していきましょう。

$ rails db:migrate

== 20180619073616 CreateLikes: migrating ======================================
-- create_table(:likes)
   -> 0.0059s
== 20180619073616 CreateLikes: migrated (0.0068s) =============================

likesテーブルが作成されました。

モデル生成では、user:references micropost:referencesと書きましたが

$ rails g model Like user:references micropost:references

実際にDBに作成されたlikesテーブルのカラムには、

  • user_id
  • micropost_id

が、出来ているとわかります。

mysql> show tables;
+----------------------------------+
| Tables_in_microposts_development |
+----------------------------------+
| ar_internal_metadata             |
| likes                            |
| microposts                       |
| relationships                    |
| schema_migrations                |
| users                            |
+----------------------------------+
6 rows in set (0.00 sec)

mysql> describe likes;
+--------------+----------+------+-----+---------+----------------+
| Field        | Type     | Null | Key | Default | Extra          |
+--------------+----------+------+-----+---------+----------------+
| id           | int(11)  | NO   | PRI | NULL    | auto_increment |
| user_id      | int(11)  | YES  | MUL | NULL    |                |
| micropost_id | int(11)  | YES  | MUL | NULL    |                |
| created_at   | datetime | NO   |     | NULL    |                |
| updated_at   | datetime | NO   |     | NULL    |                |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

reference型を使うメリット

reference型を使うメリットは、userという名前でrails g modelして、user_idというカラム名を自動で作成してくれることで、usersテーブルのidを自動で参照(インデックス)してくれます。Rails便利。


以上です!

この記事を読んだ方に

この記事を読んで、誤っている箇所をみつけたり、追記した方がいい内容などありましたら、編集リクエストやコメント欄で指摘していただけると助かります。

参考

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12