【问题标题】:Ruby: Accessing rake task from a gem without RailsRuby:从没有 Rails 的 gem 访问 rake 任务
【发布时间】:2012-12-01 06:18:52
【问题描述】:

我知道 Rake 任务可以在 Ruby gem 中的许多地方定义:

  • 在 Rakefile 中
  • tasks/*.rake
  • lib/tasks/*.rake

我已经读过,当要在 gem 本身上执行任务时,应该使用前两个。当需要公开任务时,似乎应该选择第三个选项。

有许多在线教程演示了使用 Rails 从 gem 加载 Rake 任务的各种方法,即利用 Rails::RailTie

但是,我想找到一种方法,在不需要 Rails 的情况下在另一个 gem 中使用依赖 gem 的任务。

有没有简单的解决方案?有人能描述一下正确的方法,或者概述哪些方法是可行的吗?

更新

我已尝试创建一个文件bin/my-gem,以便在系统上用于从my-gem 执行Rake 任务。我在里面放了以下内容;

#!/usr/bin/env ruby
require 'rubygems'
require 'rake'
task=ARGV[0]
spec = Gem::Specification.find_by_name('dsi_core')
Dir["#{spec.gem_dir}/lib/tasks/*.rake"].each {|file| puts file and Rake::load_rakefile(file)}
Rake::Task.clear # Avoid tasks being loaded several times in dev mode
Rake::Task[task].reenable # Support re-execution of a task.
Rake::Task[task].invoke

部分内容基于this SO post

遗憾的是,我做错了,因为在安装 gem 然后运行 ​​my-gem mytask 并在 lib/test.rake 中定义 mytask 然后输出以下内容:

/var/lib/gems/1.8/gems/rake-0.9.2/lib/rake/task_manager.rb:49:in `[]': Don't know how to build task 'mytest' (RuntimeError)
    from /var/lib/gems/1.8/gems/rake-0.9.2/lib/rake/task.rb:298:in `[]'
    from /var/lib/gems/1.8/gems/my_gem-0.0.1/bin/my_gem:8
    from /usr/local/bin/my_gem:19:in `load'
    from /usr/local/bin/my_gem:19

【问题讨论】:

  • 感谢您的链接,但这是用于执行 ruby​​ 脚本而不是 Rake 任务。它也不会为带有参数的 rake 任务提供支持。我希望能找到一个明确的rake gem::task[args]风格的执行方法。

标签: ruby-on-rails ruby rake task


【解决方案1】:

我找到了解决方案 here 的正文。我对其进行了修改以支持带参数的任务规范,并添加了对cucumber 的支持。

所以..

在您的 gem 中创建 bin/my_gem

将本文底部的脚本粘贴到其中。示例用法见 cmets。

您的rake 任务必须在您的Rakefile 中。

或者,添加您的任务,例如到lib/tasks/*.rake,然后将以下内容添加到您的Rakefile

Dir.glob('lib/tasks/*.rake').each {|r| import r}

秘诀如下:

#!/usr/bin/env ruby

# Run rake tasks and cucumber features
# from my_gem once it's installed.
#
# Example:
#
#   my_gem rake some-task
#   my_gem rake some-task[args]
#   my_gem cucumber feature1 feature2
#
# Note: cucumber features have '.feature' appended automatically,
#       no need for you to do it ;)
#
# Author:: N David Brown
gem_dir = File.expand_path("..",File.dirname(__FILE__))
$LOAD_PATH.unshift gem_dir# Look in gem directory for resources first.
exec_type = ARGV[0]
if exec_type == 'rake' then
    require 'rake'
    require 'pp'
    pwd=Dir.pwd
    Dir.chdir(gem_dir) # We'll load rakefile from the gem's dir.
    Rake.application.init
    Rake.application.load_rakefile
    Dir.chdir(pwd) # Revert to original pwd for any path args passed to task.
    Rake.application.invoke_task(ARGV[1])
elsif exec_type == 'cucumber' then
    require 'cucumber'
    features = ARGV[1,].map{|feature| "#{gem_dir}/features/#{feature}.feature"}.join(' ')
    runtime = Cucumber::Runtime.new 
    runtime.load_programming_language('rb') 
    pwd=Dir.pwd
    Dir.chdir(gem_dir) # We'll load features from the gem's dir.
    Cucumber::Cli::Main.new([features]).execute!(runtime)
    Dir.chdir(pwd) # Revert to original pwd for convenience.
end

宾果! :-)

【讨论】:

  • 这很有帮助。谢谢! :)
  • 所以要调用这个,我不能只调用rake task_name,我必须调用my_gem rake task_name,对吧?有没有办法我可以在非 Rails gem 中添加一个 Rake 任务并能够只用rake 调用它?
【解决方案2】:

这篇文章给了我一些提示,但也许对于遇到此问题的其他人,我在一些依赖问题上苦苦挣扎。我终于想出了如何使用 bin/binstub 而不需要 rakefile 来做到这一点。 My solution is posted on another SO question.

【讨论】:

    猜你喜欢
    • 2013-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 2020-12-24
    • 1970-01-01
    • 2013-08-06
    • 2011-02-09
    • 2013-09-14
    相关资源
    最近更新 更多