【问题标题】:Run rake task in controller在控制器中运行 rake 任务
【发布时间】:2010-11-13 07:09:23
【问题描述】:

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

【问题讨论】:

标签: ruby-on-rails ruby rake


【解决方案1】:

我觉得在代码中调用 rake 任务不是很好的风格。我建议将要执行的任务的代码放在 rake 任务之外的某个位置,并让 rake 任务调用此代码。

这不仅具有易于在 rake 外部调用(这是您想要的)的优点,而且还可以更轻松地测试 rake 任务。

【讨论】:

  • +1 我同意:这是应该以两种不同方式重构和调用的事物的完美示例。
  • railscasts.com/episodes/127-rake-in-background 似乎是运行 rake 的绝佳理由..
  • 对于“rake 任务之外的某个地方”来说,一个好的“某处”应该是哪里?
  • @user456584 如果与模型有关,则放在模型类中。如果它与其他内容相关,请创建一个包含它们的新文件。
  • 在我的情况下,我需要从 3rd 方库运行任务,所以我无法重构它(无需经历分叉等的麻烦)
【解决方案2】:

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

%x[rake name_task]

with: name_task 是你的任务名称

【讨论】:

  • 如何将环境传递给它?
  • 我永远不会在生产中从我的控制器中抽出。
  • @Duke 当你回答或评论时,你能否解释你的推理,而不仅仅是做出断言(生产中的控制器不应该调用 rake 任务)?这将帮助人们理解你的推理,而不是仅仅知道你不会做什么(而不是听你解释为什么)。
  • @Matt 脱壳意味着 Rake 将在另一个进程中执行。这意味着它将启动一个新的 ruby​​ 解释器。也有可能发生注入导致任意命令被执行(一些错别字远离)。
【解决方案3】:

我同意 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

您可以在初始化程序中要求 'rake' 和 .load_tasks。

【讨论】:

  • 在哪里可以找到我的“应用程序名称”?
  • @pxdleif 它在config/application.rb 中作为模块名称大约 12 行,假设您使用的是 Rails。
  • 您也可以通过调用Rails.application来引用您的应用程序
  • 这很好用!对其他人来说很清楚,此方法用于同步调用 rake 任务(页面在 rake 完成之前不会呈现)。对于异步使用,请使用此 rails cast 中的 call_rake:railscasts.com/episodes/127-rake-in-background
  • 实际上经过更多的工作,我在 Rails 3.2.13 上的应用程序只需要 Sample::Application.load_tasks 行。如果我包含 Task.clear 行,我的应用程序在我调用第一个 rake 之前一直工作,那么它会给我一个关于我为 doc:app 所做的自定义覆盖的错误。但这只是我的应用程序
【解决方案4】:

与其尝试在控制器中调用 rake 任务,不如调用包含您尝试执行的任何逻辑的服务对象。

class SomeController < ApplicationController
  def whatever
    SomeServiceObject.call
  end
end

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

namespace :example do
  desc 'important task'
  task :important_task do
    SomeServiceObject.call
  end
end

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

【讨论】:

  • 这是一种非常干净的方式。谢谢。
  • 这个概念非常简单。效果很好!我没有在SomeServiceObject 中添加代码。我正在使用self 编写模型,并像这样从 rake 任务中调用:User.subscribe_to_fcm
猜你喜欢
  • 2011-06-17
  • 2013-09-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多