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

Kom*_*ave 22 ruby rake ruby-on-rails task

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

  • 在Rakefile里面
  • tasks/*.rake
  • lib/tasks/*.rake

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

网上有很多教程演示了使用Rails从gem加载Rake任务的各种方法,即利用Rails::RailTie.

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

有一个简单的解决方案吗?有人会善意地描述正确的方法,或概述哪些方法可行?

UPDATE

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

#!/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
Run Code Online (Sandbox Code Playgroud)

部分内容基于此SO帖子.

可悲的是我,因为在安装宝石,然后运行做错事my-gem mytaskmytask定义lib/test.rake再下面是输出:

/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
Run Code Online (Sandbox Code Playgroud)

Kom*_*ave 14

我在这里找到了解决方案的主体.我修改了它以支持带参数的任务规范并增加了对它的支持cucumber.

所以..

在你的宝石创建中 bin/my_gem

将此帖子底部的脚本粘贴到其中.有关示例用法,请参阅注释

你的rake任务必须在你的Rakefile.

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

Dir.glob('lib/tasks/*.rake').each {|r| import r}
Run Code Online (Sandbox Code Playgroud)

这是秘密酱:

#!/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
Run Code Online (Sandbox Code Playgroud)

答对了!:-)