ruby Rails safety_assured和Rubocop在drop column迁移上的分歧

js4nwp54  于 2023-06-29  发布在  Ruby
关注(0)|答案(1)|浏览(112)

在我的Rails项目中,我同时使用了safety_assuredrubocop gem。我打算运行一个简单的迁移来删除一个列,沿着如下:

# db/migrate/...
+ class RemoveEnabledFromUser < ActiveRecord::Migration[7.0]
+   def up
+     #safety_assured do
+       remove_column :users, :enabled
+     #end
+   end
+ 
+   def down
+     safety_assured do
+       add_column :users, :enabled, :boolean, default: true
+     end
+   end
+ end

# db/schema.rb
  create_table "users", force: :cascade do |t|
    # ...
    t.string "name", null: false
-   t.boolean "enabled", default: true
    # ...
  end

# app/models/User.rb
  class User < ApplicationRecord
+   self.ignored_columns += ["enabled"]
    # ...
  end

safety_assured gem告诉我应该在模型中包含self.ignored_columns,而rubocop告诉我应该删除它,因为它不存在于模式(Rails/UnusedIgnoredColumns)中。
我对Rails没有经验,但我假设ActiveRecord通过查询数据库(MySQL/PostgreSQL)来推断模式,而db/schema.rb只是其他事情(例如播种开发数据库)的助手。因此,在服务器运行时,存在用户模式意外更改的危险。
在这种情况下省略ignored_columns安全吗?

camsedfj

camsedfj1#

在同一个commit(deploy)中添加ignored_columns和删除列不会添加任何东西。
假设您的部署过程与标准没有太大差异。
在当前的实现中,当您部署代码时,首先将运行迁移。旧的代码将仍然运行和服务请求,以避免停机。
当该列被删除时,这对Rails来说将是一个惊喜(数据库与刚才不同),并且可能会引发错误。
部署完成后,列不再存在,并且正如Rubocop所建议的那样,ignored_columns确实无用。
正确的方法是首先为要删除的列添加ignored_columns并部署它。
然后,并且只有在此之后,才添加迁移以在同一提交中删除列和删除ignored_columns。那就部署它。
现在,在第一次部署时,Rails将开始忽略该列,并且您不必在代码中再考虑它,但它仍然会在数据库中,以便在部署期间不会中断。
第二个部署是清理,它将删除列(已经忽略,所以没有错误),并删除ignored_columns(不需要,因为列已经消失)。
strong_migrations(safety_assured)和Rubocop在这里都是正确的。你只是误解了强大的移民。我建议你重新阅读他们的README.MD。他们告诉你:
请确保忽略该列:
...

部署代码,然后将此步骤 Package 在safety_assured {...}块。

相关问题