我有一个rake任务,需要将一个值插入多个数据库。
我想从命令行或从另一个rake任务中将这个值传递给rake任务。
我该怎么做呢?
我有一个rake任务,需要将一个值插入多个数据库。
我想从命令行或从另一个rake任务中将这个值传递给rake任务。
我该怎么做呢?
当前回答
除了kch的回答(我不知道如何留下评论,对不起):
在rake命令之前,您不必将变量指定为ENV变量。你可以像设置命令行参数一样设置它们:
rake mytask var=foo
然后从rake文件中访问这些ENV变量,就像这样:
p ENV['var'] # => "foo"
其他回答
通过向任务调用中添加符号参数,可以在rake中指定正式参数。例如:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args} of class #{args.class}"
puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"
puts "arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"
end
task :invoke_my_task do
Rake.application.invoke_task("my_task[1, 2]")
end
# or if you prefer this syntax...
task :invoke_my_task_2 do
Rake::Task[:my_task].invoke(3, 4)
end
# a task with prerequisites passes its
# arguments to it prerequisites
task :with_prerequisite, [:arg1, :arg2] => :my_task #<- name of prerequisite task
# to specify default values,
# we take advantage of args being a Rake::TaskArguments object
task :with_defaults, :arg1, :arg2 do |t, args|
args.with_defaults(:arg1 => :default_1, :arg2 => :default_2)
puts "Args with defaults were: #{args}"
end
然后,从命令行:
> rake my_task[1,false] Args were: {:arg1=>"1", :arg2=>"false"} of class Rake::TaskArguments arg1 was: '1' of class String arg2 was: 'false' of class String > rake "my_task[1, 2]" Args were: {:arg1=>"1", :arg2=>"2"} > rake invoke_my_task Args were: {:arg1=>"1", :arg2=>"2"} > rake invoke_my_task_2 Args were: {:arg1=>3, :arg2=>4} > rake with_prerequisite[5,6] Args were: {:arg1=>"5", :arg2=>"6"} > rake with_defaults Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2} > rake with_defaults['x','y'] Args with defaults were: {:arg1=>"x", :arg2=>"y"}
正如第二个示例中所演示的,如果您想使用空格,则需要在目标名称周围加上引号,以防止shell在空格处分隔参数。
查看rake中的代码。Rb, rake似乎没有解析任务字符串来提取先决条件的参数,因此不能执行task:t1 => "dep[1,2]"。为先决条件指定不同参数的唯一方法是在依赖任务操作中显式地调用它,如:invoke_my_task和:invoke_my_task_2。
注意,一些shell(如zsh)需要转义括号:
我在这两个网站上找到了答案: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.extras下访问:
task :thing, [:foo] do |task, args|
puts args[:foo] # named argument
puts args.extras # any additional arguments that were passed
end
如果你想传递命名参数(例如使用标准OptionParser),你可以使用这样的东西:
$ 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])
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脚本看起来像这样时,也许是时候寻找另一种工具来实现这一点了。
使用传统的参数样式运行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