Help us understand the problem. What is going on with this article?

Rails - has_many & belongs_to関係を既存のモデルに追加

More than 3 years have passed since last update.

既存のモデル

  • Moving
  • Room

上記のモデル間にhas_many & belongs_to関係を追加する。

やり方

各モデルのテーブルにお互いのidをforeign_keyとして追加し、マイグレートする

$ rails g migration add_room_to_movings room:references
下記のマイグレーションが生成される。間違いがないか確認。

20150725142417_add_room_to_movings.rb
class AddRoomToMovings < ActiveRecord::Migration
  def change
    add_reference :movings, :room, index: true, foreign_key: true
  end
end

$ rails g migration add_moving_to_rooms moving:references
下記のマイグレーションが生成される。間違いがないか確認。

20150725142845_add_moving_to_rooms.rb
class AddMovingToRooms < ActiveRecord::Migration
  def change
    add_reference :rooms, :moving, index: true, foreign_key: true
  end
end

$ rake db:migrate

has_manybelongs_toを関係するモデルのクラスに追加

moving.rb
class Moving < ActiveRecord::Base
  ...
  has_many :rooms, dependent: :destroy
  ...
room.rb
class Room < ActiveRecord::Base
  ...
  belongs_to :moving
  ...

これで完了。

コンソールで思い通りの振る舞いになっているか確認

$ rails console --sandbox
色々試す。本当にこれで良いのかここでよく考える。場合によってはhas_many, throughを使えばもっと効率よくデータの管理ができるかもしれない。

気が変わったら、早いうちにやり直す(許されるなら)

$ rails destroy migration add_moving_to_rooms moving:references
      invoke  active_record
      remove    db/migrate/20150725142845_add_moving_to_rooms.rb
$ rails destroy  migration add_room_to_movings room:references
      invoke  active_record
      remove    db/migrate/20150725142417_add_room_to_movings.rb

忘れずにhas_manybelongs_toをモデルのクラスから取り除くこと。

以下のタスクでschemaを更新する。

$ bundle exec rake db:drop
$ bundle exec rake db:create
$ bundle exec rake db:migrate
$ bundle exec rake db:seed

has_many, throughに変更することにした

以下のコマンドで中間テーブルのクラスとマイグレーションをつくる。

rails g model MovingRoom moving_id:integer room_id:integer
20150725172522_create_moving_rooms.rb
class CreateMovingRooms < ActiveRecord::Migration
  def change
    create_table :moving_rooms do |t|
      t.integer :moving_id
      t.integer :room_id

      t.timestamps null: false
    end
  end
end
moving_room.rb
class MovingRoom < ActiveRecord::Base
end

中間テーブルのクラスにbelongs_toを追加し、モデルを関連させる。

moving_room.rb
class MovingRoom < ActiveRecord::Base
  belongs_to :moving
  belongs_to :room
end

各モデルクラスにhas_many...through...を追加し、中間テーブル経由でお互いにアクセスできるようにする。

class Moving < ActiveRecord::Base
  ...
  has_many :moving_rooms, dependent: :destroy
  has_many :rooms, through: :moving_rooms
  ...
class Room < ActiveRecord::Base
  ...
  has_many :moving_rooms, dependent: :destroy
  has_many :movings, through: :moving_rooms
  ...

効率よくクエリできるようIndexを追加

20150726014749_add_index_to_moving_rooms.rb
class AddIndexToMovingRooms < ActiveRecord::Migration
  def change
    add_index :moving_rooms, :moving_id
    add_index :moving_rooms, :room_id
    add_index :moving_rooms, [:moving_id, :room_id], unique: true
  end
end

以上。

参考資料

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away