在控制器中运行rake任务

use*_*482 72 ruby rake ruby-on-rails

我想在我的控制器中运行一个rake任务.有没有办法做到这一点?

Gri*_*mmo 60

我同意ddfreynee,但如果你知道你需要什么代码可以是这样的:

require 'rake'

Rake::Task.clear # necessary to avoid tasks being loaded several times in dev mode
Sample::Application.load_tasks # providing your application name is 'sample'

class RakeController < ApplicationController

  def run
    Rake::Task[params[:task]].reenable # in case you're going to invoke the same task second time.
    Rake::Task[params[:task]].invoke
  end

end
Run Code Online (Sandbox Code Playgroud)

您可以在初始化程序中使用'rake'和.load_tasks.

  • 您也可以通过调用`Rails.application`来引用您的应用程序 (2认同)
  • 这很棒!对其他人来说很明显,这种方法是同步调用rake任务(在rake完成之前页面不会呈现).对于异步使用,请使用此rails的call_rake:http://railscasts.com/episodes/127-rake-in-background (2认同)

Den*_*yne 57

我觉得在代码中调用rake任务并不好.我建议在rake任务之外的某处执行要执行的任务的代码,并让rake任务调用此代码.

这不仅具有易于调用外部rake(这是你想要的)的优点,而且还使测试rake任务变得更加容易.

  • http://railscasts.com/episodes/127-rake-in-background似乎是运行耙子的绝佳理由.. (7认同)
  • +1我同意:这是一个完美的例子,应该以两种不同的方式重构和调用. (6认同)
  • 一个好的"某处"会出现在"耙子任务之外的某个地方"? (4认同)
  • 在我的情况下,我需要从第三方库运行任务,所以我无法重构它(没有经历分叉的麻烦等) (2认同)

小智 17

而不是尝试在控制器中调用rake任务,而是调用包含您尝试执行的任何逻辑的服务对象.

class SomeController < ApplicationController
  def whatever
    SomeServiceObject.call
  end
end
Run Code Online (Sandbox Code Playgroud)

...然后,假设您正在讨论自定义rake任务,请让它也调用服务对象:

namespace :example do
  desc 'important task'
  task :important_task do
    SomeServiceObject.call
  end
end
Run Code Online (Sandbox Code Playgroud)

如果您不熟悉服务对象,它们只是执行特定工作的普通旧ruby类.如果你试图调用一些默认的rake任务(即:db:migrate),我强烈建议不要从控制器那样做.


小智 16

您可以在控制器中执行此操作:

%x[rake name_task]
Run Code Online (Sandbox Code Playgroud)

with:name_task是您的任务名称

  • @Duke当你回答或评论时,你是否也可以解释你的推理而不只是做出一个断言(生产中的控制器不应该调用rake任务)?这将有助于人们理解你的推理,而不仅仅是知道你不会做什么(但没有听到你对原因的解释). (17认同)
  • @Matt炮轰意味着Rake将在另一个进程中执行.这意味着它将启动一个新的ruby解释器.它也可能发生注入,导致执行任意命令(这样做有一些错误). (6认同)
  • 我永远不会在生产中向我的控制器掏钱. (4认同)
  • 你如何将环境传递给它? (2认同)