LoginSignup
1
1

More than 3 years have passed since last update.

【Rails】既存のテーブルに関連付けを追加するには?

Posted at

解決したい問題

ユーザーと投稿を関連付けをしたく、postsテーブルにuser_idカラムを追加した。
しかし、別に新たなマイグレーションを実行するたびに、なぜかschema上で、user_idカラムが消えてしまう。

最初は関連付けに関してあまり考えず進めていた

db/migrate/20201115015429_add_user_id_to_posts.rb
class AddUserIdToPosts < ActiveRecord::Migration[6.0]
  def change
    def change
      add_column :posts, :user_id ,:integer
    end
  end
end
app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user

<!---some long code--!>
app/models/user.rb
class User < ApplicationRecord
  has_many :posts

<!---some long code--!>

postsテーブルにuser_idカラムは追加しており、postモデルにbelongs_to :user
userモデルにhas_many :postsの追加はしてある。

belongs_to :userこの宣言は、postsテーブル上の対応する外部キーカラムと整合している必要がある!

具体的にはどうするのか?

Railsガイドに下記の説明の記載を発見。

カラムの種類としてreferences (belongs_to も可) を指定することができます。たとえば次のようになります。

$ rails generate migration AddUserRefToProducts user:references

上を実行すると以下が生成されます。

class AddUserRefToProducts < ActiveRecord::Migration[5.0]
   def change
     add_reference :products, :user, foreign_key: true
   end
end

このマイグレーションを実行すると、user_idが作成され、適切なインデックスが追加されます。

referenceカラムとforeign_key外部キーを追加することにより、postsテーブルにuser_idが追加され、usersテーブルのidとつながる。

既存のマイグレーションを書き換えてみる!

はじめにpostsテーブルを作った時のマイグレーションを修正してみた。

db/migrate/20201111030002_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :content
      t.datetime :start_time
      + t.references :user, foreign_key: true
      t.timestamps
    end
  end
end

何も起こらず、これではダメなよう...

add_referenceでやってみる

上記にあったように新しくマイグレーションを作成する。

db/migrate/20210217101831_add_user_to_posts.rb
class AddUserToPosts < ActiveRecord::Migration[6.0]
  def change
    add_reference :posts, :user, foreign_key: true
  end
end
db/schema.rb
ActiveRecord::Schema.define(version: 2021_02_17_101831) do

  enable_extension "plpgsql"

  create_table "posts", force: :cascade do |t|
    t.string "title"
    t.text "content"
    t.datetime "start_time"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    + t.bigint "user_id"
    + t.index ["user_id"], name: "index_posts_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "email"

  <!--some long code--!>

  end

  + add_foreign_key "posts", "users"
end

+ t.bigint "user_id"
+ t.index ["user_id"], name: "index_posts_on_user_id"
+ add_foreign_key "posts", "users"

マイグレーションを行なうと上記の3行が追記され、user_idも適応されている!
新たなマイグレーションでuser_idが消えることもなくなった。

1
1
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
1
1