在我的Rails项目中,我同时使用了safety_assured
和rubocop
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
安全吗?
1条答案
按热度按时间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 {...}块。