Til*_*dor 1065 ruby rake command-line command-line-arguments
我有一个rake任务需要将值插入多个数据库.
我想从命令行或另一个 rake任务将此值传递给rake任务.
我怎样才能做到这一点?
Nic*_*ins 1119
您可以通过向任务调用添加符号参数来在rake中指定正式参数.例如:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args}"
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
Run Code Online (Sandbox Code Playgroud)
然后,从命令行:
> rake my_task[1,2] Args were: {:arg1=>"1", :arg2=>"2"} > 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)要求您转义括号: rake my_task\['arg1'\]
Bla*_*son 350
选项和依赖项需要在数组内部:
namespace :thing do
desc "it does a thing"
task :work, [:option, :foo, :bar] do |task, args|
puts "work", args
end
task :another, [:option, :foo, :bar] do |task, args|
puts "another #{args}"
Rake::Task["thing:work"].invoke(args[:option], args[:foo], args[:bar])
# or splat the args
# Rake::Task["thing:work"].invoke(*args)
end
end
Run Code Online (Sandbox Code Playgroud)
然后
rake thing:work[1,2,3]
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}
rake thing:another[1,2,3]
=> another {:option=>"1", :foo=>"2", :bar=>"3"}
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}
Run Code Online (Sandbox Code Playgroud)
注意:变量
task
是任务对象,除非您了解/关心Rake内部,否则不是很有帮助.
铁路注意:
如果从rails运行任务,最好通过添加来预加载环境,
=> [:environment]
这是设置相关任务的一种方法.
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
Run Code Online (Sandbox Code Playgroud)
tim*_*urb 330
除了回答kch(我没有找到如何发表评论,抱歉):
您不必ENV
在rake
命令之前将变量指定为变量.您可以像往常一样将它们设置为通常的命令行参数:
rake mytask var=foo
Run Code Online (Sandbox Code Playgroud)
并从你的rake文件中访问那些作为ENV变量,如:
p ENV['var'] # => "foo"
Run Code Online (Sandbox Code Playgroud)
Tom*_*art 106
如果你想传递命名参数(例如标准OptionParser
),你可以使用这样的东西:
$ rake user:create -- --user test@example.com --pass 123
Run Code Online (Sandbox Code Playgroud)
请注意--
,这是绕过标准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
Run Code Online (Sandbox Code Playgroud)
exit
最后将确保额外的参数不会被解释为Rake任务.
参数的快捷方式也应该有效:
rake user:create -- -u test@example.com -p 123
Run Code Online (Sandbox Code Playgroud)
当rake脚本看起来像这样时,也许是时候寻找另一个允许这个开箱即用的工具了.
Til*_*dor 58
我从这两个网站找到了答案:Net Maniac和Aimred.
你需要有版本> 0.8的rake来使用这种技术
正常的rake任务描述如下:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Run Code Online (Sandbox Code Playgroud)
要传递参数,请执行以下三项操作:
要访问脚本中的参数,请使用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
Run Code Online (Sandbox Code Playgroud)
要从命令行调用此任务,请将参数传递给[] s
rake task_name['Hello',4]
Run Code Online (Sandbox Code Playgroud)
将输出
Hello
Hello
Hello
Hello
Run Code Online (Sandbox Code Playgroud)
如果要从另一个任务调用此任务,并传递参数,请使用invoke
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
Run Code Online (Sandbox Code Playgroud)
那么命令
rake caller
Run Code Online (Sandbox Code Playgroud)
将输出
In Caller
hi
hi
Run Code Online (Sandbox Code Playgroud)
我没有找到一种方法来传递参数作为依赖项的一部分,因为以下代码中断:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end
Run Code Online (Sandbox Code Playgroud)
kch*_*kch 29
另一个常用选项是传递环境变量.在您的代码中,您ENV['VAR']
可以通过它读取它们,并且可以在rake
命令之前传递它们,例如
$ VAR=foo rake mytask
Run Code Online (Sandbox Code Playgroud)
fl0*_*00r 28
实际上@Nick Desjardins回答得很完美.但仅仅是为了教育:你可以使用肮脏的方法:使用ENV
参数
task :my_task do
myvar = ENV['myvar']
puts "myvar: #{myvar}"
end
rake my_task myvar=10
#=> myvar: 10
Run Code Online (Sandbox Code Playgroud)
Nat*_*ink 27
我无法弄清楚如何传递args以及:环境,直到我解决了这个问题:
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
Run Code Online (Sandbox Code Playgroud)
然后我这样打电话:
rake db:export['foo, /tmp/']
Run Code Online (Sandbox Code Playgroud)
Fen*_*eng 23
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
puts args[:arg1]
end
Run Code Online (Sandbox Code Playgroud)
jas*_*ssa 19
我只是希望能够运行:
$ rake some:task arg1 arg2
Run Code Online (Sandbox Code Playgroud)
简单吧?(不!)
Rake解释arg1
并arg2
作为任务,并尝试运行它们.所以我们只是在它之前中止.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Run Code Online (Sandbox Code Playgroud)
拿那个,括号!
免责声明:我希望能够在一个非常小的宠物项目中做到这一点.不适合"现实世界"使用,因为您失去了链接rake任务的能力(即rake task1 task2 task3
).IMO不值得.只是用丑陋的rake task[arg1,arg2]
.
小智 15
namespace :namespace1 do
task :task1, [:arg1, :arg2, :arg3] => :environment do |_t, args|
p args[:arg1]
end
end
Run Code Online (Sandbox Code Playgroud)
呼叫
rake namespace1:task1["1","2","3"]
调用时无需提供环境
在 zsh 中需要将调用括在引号中
rake 'namespace1:task1["1","2","3"]'
djb*_*ick 12
我在rake文件中使用常规ruby参数:
DB = ARGV[1]
Run Code Online (Sandbox Code Playgroud)
然后我将文件底部的rake任务存根(因为rake将根据该参数名称查找任务).
task :database_name1
task :database_name2
Run Code Online (Sandbox Code Playgroud)
命令行:
rake mytask db_name
Run Code Online (Sandbox Code Playgroud)
这对我来说比var = foo ENV var和任务args [blah,blah2]解决方案感觉更干净.
如果您只有一些一次性设置的环境,那么存根有点粗糙,但也不会太糟糕
要使用传统参数样式运行 rake 任务:
rake task arg1 arg2
Run Code Online (Sandbox Code Playgroud)
然后使用:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Run Code Online (Sandbox Code Playgroud)
添加以下 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
Run Code Online (Sandbox Code Playgroud)
在上面的答案中,传递参数的方法是正确的.但是,要使用参数运行rake任务,较新版本的rails会涉及一个小技术问题
它将与rake"namespace:taskname ['argument1']"一起使用
请注意从命令行运行任务时的反向引号.
我在这里没有看到的一件事是如何处理任意参数。如果您传递任务定义中未列出的参数,仍然可以在以下位置访问它们args.extras
:
task :thing, [:foo] do |task, args|
puts args[:foo] # named argument
puts args.extras # any additional arguments that were passed
end
Run Code Online (Sandbox Code Playgroud)