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

我想从命令行或从另一个rake任务中将这个值传递给rake任务。

我该怎么做呢?


当前回答

我在这两个网站上找到了答案:Net Maniac和Aimred。

您需要拥有版本> 0.8的rake才能使用这种技术

正常的rake任务描述如下:

desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
  #interesting things
end

要传递参数,需要做三件事:

在任务名称之后添加参数名称,以逗号分隔。 将依赖项放在最后,使用:needs =>[…] 把|t, args|放在do后面。(t为本次任务的对象)

要访问脚本中的参数,请使用args.arg_name

desc 'Takes arguments task'
task :task_name, :display_value, :display_times, :needs => [:depends_on_taskA, :depends_on_taskB] do |t, args|
  args.display_times.to_i.times do
    puts args.display_value
  end
end

要从命令行调用此任务,请将[]s中的参数传递给它

rake task_name['Hello',4]

将输出

Hello
Hello
Hello
Hello

如果你想从另一个任务调用这个任务,并给它传递参数,使用invoke

task :caller do
  puts 'In Caller'
  Rake::Task[:task_name].invoke('hi',2)
end

然后命令

rake caller

将输出

In Caller
hi
hi

我还没有找到一种方法来传递参数作为依赖的一部分,如下代码中断:

task :caller => :task_name['hi',2]' do
   puts 'In Caller'
end

其他回答

我不知道如何传递args和:environment,直到我解决了这个问题:

namespace :db do
  desc 'Export product data'
  task :export, [:file_token, :file_path] => :environment do |t, args|
    args.with_defaults(:file_token => "products", :file_path => "./lib/data/")

       #do stuff [...]

  end
end

然后我这样调用:

rake db:export['foo, /tmp/']

如果你懒得记参数位置是什么你想做一些类似ruby参数哈希的东西。您可以使用一个参数传入一个字符串,然后将该字符串正则化为一个选项散列。

namespace :dummy_data do
  desc "Tests options hash like arguments"
  task :test, [:options] => :environment do |t, args|
    arg_options = args[:options] || '' # nil catch incase no options are provided
    two_d_array = arg_options.scan(/\W*(\w*): (\w*)\W*/)
    puts two_d_array.to_s + ' # options are regexed into a 2d array'
    string_key_hash = two_d_array.to_h
    puts string_key_hash.to_s + ' # options are in a hash with keys as strings'
    options = two_d_array.map {|p| [p[0].to_sym, p[1]]}.to_h
    puts options.to_s + ' # options are in a hash with symbols'
    default_options = {users: '50', friends: '25', colour: 'red', name: 'tom'}
    options = default_options.merge(options)
    puts options.to_s + ' # default option values are merged into options'
  end
end

在命令行中。

$ rake dummy_data:test["users: 100 friends: 50 colour: red"]
[["users", "100"], ["friends", "50"], ["colour", "red"]] # options are regexed into a 2d array
{"users"=>"100", "friends"=>"50", "colour"=>"red"} # options are in a hash with keys as strings
{:users=>"100", :friends=>"50", :colour=>"red"} # options are in a hash with symbols
{:users=>"100", :friends=>"50", :colour=>"red", :name=>"tom"} # default option values are merged into options

我只是想能够奔跑:

$ rake some:task arg1 arg2

简单,是吧?(不!)

Rake将arg1和arg2解释为任务,并尝试运行它们。所以我们要赶在它之前中止。

namespace :some do
  task task: :environment do
    arg1, arg2 = ARGV

    # your task...

    exit
  end
end

听着,括号!

免责声明:我希望能够在一个相当小的宠物项目中做到这一点。不打算用于“真实世界”,因为您失去了链耙任务的能力(即耙task1 task2 task3)。我觉得不值得。只需使用丑陋的rake任务[arg1,arg2]。

除了kch的回答(我不知道如何留下评论,对不起):

在rake命令之前,您不必将变量指定为ENV变量。你可以像设置命令行参数一样设置它们:

rake mytask var=foo

然后从rake文件中访问这些ENV变量,就像这样:

p ENV['var'] # => "foo"

使用传统的参数样式运行rake任务:

rake task arg1 arg2

然后使用:

task :task do |_, args|
  puts "This is argument 1: #{args.first}"
end

添加以下rake gem补丁:

Rake::Application.class_eval do

  alias origin_top_level top_level

  def top_level
    @top_level_tasks = [top_level_tasks.join(' ')]
    origin_top_level
  end

  def parse_task_string(string) # :nodoc:
    parts = string.split ' '
    return parts.shift, parts
  end

end

Rake::Task.class_eval do

  def invoke(*args)
    invoke_with_call_chain(args, Rake::InvocationChain::EMPTY)
  end

end