覆盖 Rail 的默认 rake 任务

我有一个 Rails 2.2项目,其中我想覆盖 rake db:test:prepare任务的功能。我以为这会有用,但没用:

#lib/tasks/db.rake
namespace :db do
namespace :test do
desc "Overridden version of rails' standard db:test:prepare task since the schema dump used in that can't handle DB enums"
task :prepare => [:environment] do
puts "doing db:structure:dump"
Rake::Task['db:structure:dump'].invoke
puts "doing db:test:clone_structure"
Rake::Task['db:test:clone_structure'].invoke
end
end
end

我理解标准任务的行为。如果我将任务的名称改为 :prepare2,然后执行 rake db:test:prepare2,那么它就可以正常工作。我从中得出的自然结论是,我的 rake 任务被定义为 之前内置的 Rails 任务,所以我的任务被标准的 :prepare任务覆盖。

有人知道我该怎么补救吗?我宁愿覆盖它,也不要使用新任务。谢谢 Max

23696 次浏览

在添加自己的任务之前,必须删除默认任务:

Rake.application.instance_variable_get('@tasks').delete('db:test:prepare')
namespace 'db' do
namespace 'test' do
task 'prepare' do
# ...
end
end
end

相当流行的成语是创建一个方便的方法,称为 remove_task,如下所示:

Rake::TaskManager.class_eval do
def remove_task(task_name)
@tasks.delete(task_name.to_s)
end
end


def remove_task(task_name)
Rake.application.remove_task(task_name)
end

(资料来源: drnic/newgem)

如果定义了已经存在的 rake 任务,则其执行将追加到原始任务的执行之后; 两个任务都将执行。

如果你想重新定义一个任务,你需要先清除原始任务:

Rake::Task["db:test:prepare"].clear

还需要注意的是,一旦在 rake 中执行了任务,即使您再次调用它,它也不会再次执行。这是按照设计的,但是您可以对任务调用 .reset以允许它再次运行。

Lib/task/创建一个新的 项目 Rake文件,并将下面的代码粘贴到其中。

namespace :mv do
desc "Display hint and info for your rails 4 project"
task info: :environment do
puts 'Run rake test to test'
end
end


task(:default).clear.enhance ['mv:info']

Krasimir Angelov 的博客的启发