如何将命令行参数传递给rake任务

我有一个rake任务须要将值插入多个数据库。 git

我想从命令行或另外一个 rake任务将此值传递给rake任务。 github

我怎样才能作到这一点? 数据库


#1楼

desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end

#2楼

我在rake文件中使用常规ruby参数: 数组

DB = ARGV[1]

而后我将文件底部的rake任务存根(由于rake将根据该参数名称查找任务)。 ruby

task :database_name1
task :database_name2

命令行: 工具

rake mytask db_name

这对我来讲比var = foo ENV var和任务args [blah,blah2]解决方案感受更干净。
若是您只有一些一次性设置的环境,那么存根有点粗糙,但也不会太糟糕 ui


#3楼

若是你想传递命名参数(例如使用标准的OptionParser ),你可使用这样的东西: spa

$ rake user:create -- --user test@example.com --pass 123

注意-- ,这是绕过标准Rake参数所必需的。 应该使用Rake 0.9.x<= 10.3.x。 命令行

较新的Rake改变了它的解析--如今你必须确保它没有传递给OptionParser#parse方法,例如使用parser.parse!(ARGV[2..-1]) code

require 'rake'
require 'optparse'
# Rake task for creating an account

namespace :user do |args|
  desc 'Creates user account with given credentials: rake user:create'
  # environment is required to have access to Rails models
  task :create do
    options = {}
    OptionParser.new(args) do |opts|
      opts.banner = "Usage: rake user:create [options]"
      opts.on("-u", "--user {username}","User's email address", String) do |user|
        options[:user] = user
      end
      opts.on("-p", "--pass {password}","User's password", String) do |pass|
        options[:pass] = pass
      end
    end.parse!

    puts "creating user account..."
    u = Hash.new
    u[:email] = options[:user]
    u[:password] = options[:pass]
    # with some DB layer like ActiveRecord:
    # user = User.new(u); user.save!
    puts "user: " + u.to_s
    puts "account created."
    exit 0
  end
end

exit将确保额外的参数不会被解释为Rake任务。

参数的快捷方式也应该有效:

rake user:create -- -u test@example.com -p 123

当rake脚本看起来像这样时,也许是时候寻找另外一个容许这个开箱即用的工具了。


#4楼

要将参数传递给默认任务,您能够执行相似的操做。 例如,说“版本”是你的参数:

task :default, [:version] => [:build]

task :build, :version do |t,args|
  version = args[:version]
  puts version ? "version is #{version}" : "no version passed"
end

而后你能够像这样调用它:

$ rake
no version passed

要么

$ rake default[3.2.1]
version is 3.2.1

要么

$ rake build[3.2.1]
version is 3.2.1

可是,我没有找到一种方法来避免在传入参数时指定任务名称(默认或构建)。 若是有人知道某种方式,我很乐意听到。


#5楼

我喜欢参数传递的“查询字符串”语法,特别是当有不少参数要传递时。

例:

rake "mytask[width=10&height=20]"

“querystring”是:

width=10&height=20

警告:请注意语法是rake "mytask[foo=bar]"不是 rake mytask["foo=bar"]

使用Rack::Utils.parse_nested_query在rake任务中解析时,咱们获得一个Hash

=> {"width"=>"10", "height"=>"20"}

(很酷的是你能够传递哈希和数组,下面更多)

这是如何实现这个目标的:

require 'rack/utils'

task :mytask, :args_expr do |t,args|
  args.with_defaults(:args_expr => "width=10&height=10")
  options = Rack::Utils.parse_nested_query(args[:args_expr])
end

这是我在delayed_job_active_record_threaded gem中使用Rails的更加扩展的示例:

bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"

以与上面相同的方式解析,具备环境依赖性(为了加载Rails环境)

namespace :dj do
  task :start, [ :args_expr ] => :environment do |t, args|
    # defaults here...
    options = Rack::Utils.parse_nested_query(args[:args_expr])  
  end
end

options给出如下内容

=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}