如何在迁移文件中执行 Rake 任务?

57

我有一个Rake任务,可以从文件中将配置数据加载到数据库中,有没有正确的ruby/rails方法在迁移up时调用它?

我的目标是同步我的团队数据库配置,而无需广播然后运行任务lalala

  def self.up
    change_table :fis_situacao_fiscal do |t|
      t.remove :mostrar_endereco
      t.rename :serie, :modelo 
    end

    Faturamento::Cfop.destroy_all()
    #perform rake here !
  end

更新 现在我该怎么做,以下方法可行:

system('rake sistema:load_data file=faturamento/cfop')

以下是来自@Ryan Bigg的建议,以及它的异常情况:

Rake::Task['rake sistema:load_data file=faturamento/cfop'].invoke()

.

==  AlterSituacaoFiscalModeloEndereco: migrating ====================
-- change_table(:fis_situacao_fiscal)
   -> 0.0014s

rake aborted!
An error has occurred, this and all later migrations canceled:

Don't know how to build task 'rake sistema:load_data file=faturamento/cfop'

出了什么问题?


3
为什么要传递单词“rake”?试试不传。它知道这是一个rake任务。 - ryeguy
4个回答

95

是的!有一种方法可以做到。

运行以下命令。

Rake::Task['your_task'].invoke

更新解决方案

不要在括号内放置Rake,只需放置任务的名称。建议您在控制台中运行以下命令时设置一个ENV变量。

FILE=somefile.text rake db:sistema:load_data

您可以使用以下示例单独调用它。

FILE=somefile.text rake some:other:task:that:calls:it

它将作为ENV ['file']在您的任务中可用。


我已经根据你的答案进行了更新,如果你能再帮忙一些就太好了。 - Fabiano Soriani
3
如果任务在命名空间中怎么办?我有一个种子系统,可以使用 rake semi:seed[89] 命令来运行(将运行以 89_ 开头的 .rb 文件),但我无法通过 Rake::Task['semi:seed[89]'] 命令来调用它。你有想法如何在迁移文件中调用种子任务吗? - MrYoshiji
4
抱歉,我刚才只需要在调用时传递89个参数:Rake::Task['semi:seed'].invoke('89')就可以正常工作了。 - MrYoshiji
还有其他人收到了 You have 1 pending migrations: 的提示吗?在迁移过程中,它不允许运行另一个 rake 任务。 - Joshua Pinter
如果您不知道任务的名称,请运行 rake -T -A 以获取完整列表。 - aclima

10

请注意,如果您使用'system'调用Rake任务,则需要在调用后检查进程状态,如果Rake任务失败,则必须引发异常。否则,即使Rake任务失败,迁移也将成功。

您可以按照以下方式检查进程状态:

if !($?.success?)
  raise "Rake task failed"
end

使用rake任务是更好的选择 - 如果Rake任务失败,它将导致迁移失败。


7
你可以使用 Rake::Task['namespace:task'].invoke 或者 Rake::Task['namespace:task'].execute 在已经加载的 Rails 环境中执行 rake 任务。
你可以在 invoke 或者 execute 方法中传递数据给任务。例如:
Rake::Task['namespace:task'].invoke(paramValue)

在rake任务中,可以按照以下方式处理此参数:
namespace :namespace do
  desc "Example description."
  task :task, [:param] => :environment do |t, args|
    puts args[:param]
    ...
  end
end

这可以在控制台上执行,如下所示:
bundle exec rake namespace:task[paramValue]

更多信息: https://medium.com/@sampatbadhe/rake-task-invoke-or-execute-419cd689c3bd

1

这个决定 更符合我的看法。

对于你的情况,应该是这样的:

backup_env = ENV.slice('file') if ENV.key?('file')
ENV['file'] = 'faturamento/cfop'
Rake::Task['sistema:load_data'].invoke
ENV.delete 'file'
ENV.merge!(backup_env) if backup_env

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接