0
0

More than 1 year has passed since last update.

rails d modelは要注意

Last updated at Posted at 2022-02-11

開発中のアプリケーションでいらないモデルを削除しようとなったときに、rails d modelをしてしまい(もちろんpushはしてない)「そのやり方は100%ダメだ」と言われることがあったので自戒の念を込めて記事を作成します。

rails newで実験用アプリを用意する

rails new migration_experiment
cd migration_experiment
rails db:create

User modelを作成する

rails g model User name:string
rails db:migrate

Task modelを作成する

rails g model Task name:text description:text
rails db:migrate

User modelにemailカラムを追加する

アプリを作成中User modelに新しくemailカラムを追加することになったと仮定してemailカラムを追加するmigrationファイルを作成します。

rails g migration add_email_to_users
20220211072145_add_email_to_users.rb
class AddEmailToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :email, :string
  end
end
rails db:migrate

この時点でのmigrationファイルの状態が以下です。

20220211071814_create_users.rb
20220211071830_create_tasks.rb
20220211072145_add_email_to_users.rb

rails d model を実行する

さて、ここからが問題のrails d modelの実行です。

rails d model User

こちらを実行すると、migrationファイルの状態がこのようになります。

20220211071830_create_tasks.rb
20220211072145_add_email_to_users.rb

raisl d model前には存在していたUser modelを作成した際のmigrationファイルがなくなっています。この状態でrails db:migrate:resetを実行するとどうなるでしょうか?

== 20220211071830 CreateTasks: migrating ======================================
-- create_table(:tasks)
   -> 0.0022s
== 20220211071830 CreateTasks: migrated (0.0023s) =============================

== 20220211072145 AddEmailToUsers: migrating ==================================
-- add_column(:users, :email, :string)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: no such table: users

User modelを削除してしまったので、emailカラムを追加するmigrationファイルが適用できずエラーが出てしまっています。

なぜこのようなことが起こってしまうかというと、「rails d model」では、

remove  db/migrate/20220211073521_create_users.rb
remove  app/models/user.rb

<!--その他の削除されるファイルは割愛-->

の様にmodel自体とmodelを作成したmigrationファイルのみを削除し、そのモデルに新しいカラムを追加したファイルは削除されません。なのでmigrationファイルの整合性が取れなくなるためエラーが発生してしまうことになります。

今は実験のため3つのmigration fileを一人でいじっているだけなので他のmaigrationファイルを全て削除し、新しくモデルを作成(新しいmigrationファイルの作成)後、migrate:resetをかければ元通りの状態までは簡単に持っていけます。しかしチーム開発や、model数が多くなってきた場合そういった作業をするわけにはいきません。

では、不要になったmodelを削除する場合はどうすればいいのでしょうか?

モデルを削除するmigrationファイルを作成する

安全にモデルを削除するにはそのモデルを削除することを宣言するmigrationファイルを作成します。

rails g migration drop_table_users

ファイルを編集します。

20220211080417_drop_table_users.rb
class DropTableUsers < ActiveRecord::Migration[6.1]
  def change
    drop_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps null: false
    end
  end
end
rails db:migrate

このような作業を経ることによってmigrationファイルの整合性が保たれ、後に新しいmodel作成をしたmigrationファイルが積み上がってきたり、rails db:migrate:resetを実行したときにもエラーを起こさず進めていくことができます。

おまけ

今回モデルを綺麗に削除してmigrationファイルの整合性を保つような作業をしましたが、一度modelを削除したり、rails db:migrate:resetをかけると当然の様にDBにあるデータは戻ってきません。一度dumpしたファイルの内容を全て消してしまいとてもめんどくさいことになったことがあるので皆さんご注意を。

0
0
1

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