测试迁移时如何暂时禁用 "needs_migration?" 检查?
How temporarily disable "needs_migration?" check when testing migration?
我已经编写了规范来测试我的迁移,但是当我 运行 它时,我得到了一个错误:
ActiveRecord::PendingMigrationError:
Migrations are pending. To resolve this issue, run:
bin/rake db:migrate RAILS_ENV=test
我试图在 before
部分禁用迁移检查,但该检查 运行ning 在所有测试之前。
如何禁用迁移检查以进行测试?
在config/environments/test.rb
中添加行
config.active_record.migration_error = false
测试 Rails 迁移有点痛苦,所以我宁愿退后一步,想想这是否需要在 Rails 迁移中/在 Rails 迁移中测试.
基本上有两种不同类型的迁移
架构迁移
主要使用 Rails 内置函数。除非你做一些手工制作 SQL 我不会费心测试这个并相信这里的框架。
数据迁移
数据迁移用于回填或更改数据。由于数据是您最宝贵的资产之一,丢失或损坏它是非常痛苦的,所以我绝对建议为数据迁移编写测试。
如前所述,测试迁移有点麻烦,所以我会尝试在它自己的(服务)class 中抽象数据迁移代码。像
class DataMigration::UpdateUsername
def self.run
new.run
end
def run
User.all do |batch|
user.update(name: user.name.capitalize)
end
end
end
您现在可以像正常 class 一样测试数据迁移,如下所示:
it 'does capitalize the name' do
user = create(:user, name: 'name')
DataMigration::UpdateUsername.run
expect(user.reload.name).to eq('NAME')
end
现在我们可以在 Rails 迁移中使用此 class 或者例如只需在 Rake 任务中使用它。在 Rake 任务中使用它还有一个优点,我们可以传入参数,运行 多个并行数据迁移(例如,你有一个大数据集),甚至在你不能在 Rails迁移。
示例
class DataMigration::UpdateUsername
def initialize(start_id:, finish_id:)
@start_id = start_id
@finish_id = finish_id
end
def run
User.find_in_batches(start: start_id, finish: finish_id) do |batch|
batch.each do |user|
user.update(name: user.name.capitalize)
end
end
end
end
现在我们可以为此创建一个自定义任务
namespace :db do
desc "Runs user data migration"
task :update_user, [:start, :finish] do |task, args|
DataMigration::UpdateUsername.new(start_id: args[:start], finish_id: args[:finish])
end
end
rake db:update_user[0, 10000]
rake db:update_user[10000, 20000]
# ...
我已经编写了规范来测试我的迁移,但是当我 运行 它时,我得到了一个错误:
ActiveRecord::PendingMigrationError:
Migrations are pending. To resolve this issue, run:
bin/rake db:migrate RAILS_ENV=test
我试图在 before
部分禁用迁移检查,但该检查 运行ning 在所有测试之前。
如何禁用迁移检查以进行测试?
在config/environments/test.rb
中添加行
config.active_record.migration_error = false
测试 Rails 迁移有点痛苦,所以我宁愿退后一步,想想这是否需要在 Rails 迁移中/在 Rails 迁移中测试.
基本上有两种不同类型的迁移
架构迁移
主要使用 Rails 内置函数。除非你做一些手工制作 SQL 我不会费心测试这个并相信这里的框架。
数据迁移
数据迁移用于回填或更改数据。由于数据是您最宝贵的资产之一,丢失或损坏它是非常痛苦的,所以我绝对建议为数据迁移编写测试。
如前所述,测试迁移有点麻烦,所以我会尝试在它自己的(服务)class 中抽象数据迁移代码。像
class DataMigration::UpdateUsername
def self.run
new.run
end
def run
User.all do |batch|
user.update(name: user.name.capitalize)
end
end
end
您现在可以像正常 class 一样测试数据迁移,如下所示:
it 'does capitalize the name' do
user = create(:user, name: 'name')
DataMigration::UpdateUsername.run
expect(user.reload.name).to eq('NAME')
end
现在我们可以在 Rails 迁移中使用此 class 或者例如只需在 Rake 任务中使用它。在 Rake 任务中使用它还有一个优点,我们可以传入参数,运行 多个并行数据迁移(例如,你有一个大数据集),甚至在你不能在 Rails迁移。
示例
class DataMigration::UpdateUsername
def initialize(start_id:, finish_id:)
@start_id = start_id
@finish_id = finish_id
end
def run
User.find_in_batches(start: start_id, finish: finish_id) do |batch|
batch.each do |user|
user.update(name: user.name.capitalize)
end
end
end
end
现在我们可以为此创建一个自定义任务
namespace :db do
desc "Runs user data migration"
task :update_user, [:start, :finish] do |task, args|
DataMigration::UpdateUsername.new(start_id: args[:start], finish_id: args[:finish])
end
end
rake db:update_user[0, 10000]
rake db:update_user[10000, 20000]
# ...