Ruby: 如何在没有Rails的情况下访问gem中的rake任务

23
我知道Rake任务可以在Ruby gem的许多地方定义:
- 在Rakefile中 - 在 tasks/*.rake 中 - 在 lib/tasks/*.rake 中
当任务要在gem本身上执行时,应使用前两个选项。当希望公开任务时,应选择第三个选项。
有许多在线教程演示了从一个gem中使用Rails加载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

这篇文章的部分内容基于这篇 Stack Overflow 帖子

不幸的是,我做错了什么。在安装完 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] 风格的执行方法。 - KomodoDave
2个回答

14

我在这里找到了解决方案的内容。我已经修改它以支持带参数的任务规范,并添加了对的支持。

所以...

在你的gem中创建bin/my_gem

将本帖底部的脚本粘贴到其中。请参阅注释,了解示例用法。

您的任务必须在您的中。

或者,将您的任务添加到例如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 调用它吗? - GMA

2

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