質問: 独学でRubyとRuby on Railsを勉強しています、初心者です。 Ruby on Railsの外部キー制約について質問があります。 よろしくお願いいたします。 今、独学で簡単なブログサイトを開発しております。 Modelの構造は以下の通りです。 ``` class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :name, null: false # ユーザー名 t.string :email # メールアドレス t.integer :gender, null: false, default: 0 # 性別(0:男性, 1:女性) t.timestamps null: false end end end ``` ``` class CreatePosts < ActiveRecord::Migration def change create_table :posts do |t| t.references :user, null: false # 外部キー t.string :title, null: false # タイトル t.text :content # 投稿の内容 t.timestamps null: false end add_index :posts, :user_id add_foreign_key :posts, :users end end ``` ``` class CreateComments < ActiveRecord::Migration def change create_table :comments do |t| t.references :user, null: false # 外部キー t.references :post, null: false # 外部キー t.text :content # コメントの内容 t.timestamps null: false end end end ``` ここで、1つ質問なのですが Post(投稿)のModelには「add_foreign_key :posts, :users」という風に外部キー制約を記載しておりますが Comment(コメント)のModelには外部キー制約を記載しておりませんが、アプリケーションは正常に動作いたします! 質問したい内容は以下の2点です。 1外部キー制約とは、どのような場合に必要になるのでしょうか? 2また、comment(コメント)のModelには外部キー制約を記載していないのにアプリケーションは何故、正常に動作するのでしょうか? アドバイスなどよろしくお願いいたします。
回答: まず、「外部キー制約」は、たとえば`add_foreign_key :posts, :users`の場合には**データベースレベルで**`posts.user_id`に`users.id`にある値しか入れられないようにする(それ以外の値を入れようとすればエラーになる)、という仕組みです。 > > 2また、comment(コメント)のModelには外部キー制約を記載していないのにアプリケーションは何故、正常に動作するのでしょうか? > > > 上述したように、外部キー制約は「関係ない値を入れればエラーにする」ための仕組みなので、正しい値を入れ続ける限りにおいては、あってもなくても動作は全く変わりません。 > > 1外部キー制約とは、どのような場合に必要になるのでしょうか? > > > 性質上、「外部キー制約がなければ正しく動かない」という場面はありませんが、`references`列に余計なものが入ってしまうとあとあと混乱の原因にしかなりませんので、それをデータベースレベルで防げる外部キー制約は、基本的に付けておくことをおすすめします。 なお、Rails(少なくとも4.2以降)のマイグレーションでは、`refernces`に`foreign_key: true`を足せば外部キー制約を付けられます。別行に`add_foreign_key`を書く必要はありません。また、仕組み上外部キー制約にはインデックスが必要ですが、なければ自動生成されます。