Ruby-on-rails 如何将参数传递给具有 Rails 环境的 Rake 任务?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1357639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to pass arguments into a Rake task with environment in Rails?
提问by Will
I am able to pass in arguments as follows:
我可以按如下方式传递参数:
desc "Testing args"
task: :hello, :user, :message do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{args[:user]}. #{:message}"
end
I am also able to load the current environment for a Rails application
我还能够为 Rails 应用程序加载当前环境
desc "Testing environment"
task: :hello => :environment do
puts "Hello #{User.first.name}."
end
What I would like to do is be able to have variables and environment
我想做的是能够拥有变量和环境
desc "Testing environment and variables"
task: :hello => :environment, :message do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{User.first.name}. #{:message}"
end
But that is not a valid task call. Does anyone know how I can achieve this?
但这不是有效的任务调用。有谁知道我如何实现这一目标?
采纳答案by hgmnz
TLDR;
TLDR;
task :t, [args] => [deps]
Original Answer
原答案
When you pass in arguments to rake tasks, you can require the environment using the :needs option. For example:
当您将参数传递给 rake 任务时,您可以使用 :needs 选项来要求环境。例如:
desc "Testing environment and variables"
task :hello, :message, :needs => :environment do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{User.first.name}. #{args.message}"
end
Updated per @Peiniau's comment below
根据下面@Peiniau 的评论更新
As for Rails > 3.1
至于 Rails > 3.1
task :t, arg, :needs => [deps] # deprecated
Please use
请用
task :t, [args] => [deps]
回答by inger
Just to follow up on this old topic; here's what I think a current Rakefile (since a long ago) should do there. It's an upgraded and bugfixed version of the current winning answer (hgimenez):
只是为了跟进这个老话题;这是我认为当前的 Rakefile(很久以前)应该在那里做的事情。这是当前获胜答案 (hgimenez) 的升级和错误修正版本:
desc "Testing environment and variables"
task :hello, [:message] => :environment do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{User.first.name}. #{args.message}" # Q&A above had a typo here : #{:message}
end
This is how you invoke it (http://guides.rubyonrails.org/v4.2/command_line.html#rake):
这是您调用它的方式(http://guides.rubyonrails.org/v4.2/command_line.html#rake):
rake "hello[World]"
For multiple arguments, just add their keywords in the array of the task declaration (task :hello, [:a,:b,:c]...), and pass them comma separated:
对于多个参数,只需将它们的关键字添加到任务声明 ( task :hello, [:a,:b,:c]...)的数组中,并将它们以逗号分隔:
rake "hello[Earth,Mars,Sun,Pluto]"
Note: the number of arguments is not checked, so the odd planet is left out:)
注意:没有检查参数的数量,所以奇数行星被排除在外:)
回答by mikezter
Just for completeness, here the example from the docsmentioned above:
为了完整起见,这里是上述文档中的示例:
task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
args.with_defaults(:first_name => "John", :last_name => "Dough")
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
Notes:
笔记:
- You may omit the
#with_defaultscall, obviously. - You have to use an
Arrayfor your arguments, even if there is only one. - The prerequisites do not need to be an
Array. argsis an instance ofRake::TaskArguments.tis an instance ofRake::Task.
#with_defaults显然,您可以省略调用。- 您必须使用 an
Array作为您的参数,即使只有一个。 - 先决条件不需要是
Array. args是 的一个实例Rake::TaskArguments。t是 的一个实例Rake::Task。
回答by Dogweather
An alternate way to go about this: use OS environment variables. Benefits of this approach:
解决此问题的另一种方法:使用操作系统环境变量。这种方法的好处:
- All dependent rake tasks get the options.
- The syntax is a lot simpler, not depending on the rake DSL which is hard to figure out and changes over time.
- 所有相关的 rake 任务都获得了选项。
- 语法要简单得多,不依赖于难以理解和随时间变化的 rake DSL。
I have a rake task which requires three command-line options. Here's how I invoke it:
我有一个需要三个命令行选项的 rake 任务。这是我调用它的方式:
$ rake eaternet:import country=us region=or agency=multco
That's very clean, simple, and just bash syntax, which I like. Here's my rake task. Also very clean and no magic:
这非常干净、简单,而且只是我喜欢的 bash 语法。这是我的耙子任务。也很干净,没有魔法:
task import: [:environment] do
agency = agency_to_import
puts "Importing data for #{agency}..."
agency.import_businesses
end
def agency_to_import
country_code = ENV['country'] or raise "No country specified"
region_slug = ENV['region'] or raise "No region specified"
agency_slug = ENV['agency'] or raise "No agency specified"
Agency.from_slugs(country_code, region_slug, agency_slug)
end
This particular example doesn't show the use of dependencies. But if the :importtask did depend on others, they'd also have access to these options. But using the normal rake options method, they wouldn't.
此特定示例未显示依赖项的使用。但如果:import任务确实依赖于其他人,他们也可以访问这些选项。但是使用正常的佣金选项方法,他们不会。
回答by Lonny Eachus
While these solutions work, in my opinion this is overly complicated.
虽然这些解决方案有效,但在我看来这过于复杂。
Also, if you do it this way in zsh, you'll get errors if the brackets in your array aren't escaped with '\'.
另外,如果你在 zsh 中这样做,如果数组中的括号没有用“\”转义,你会得到错误。
I recommend using the ARGV array, which works fine, is much simpler, and is less prone to error. E.g:
我建议使用 ARGV 数组,它工作正常,简单得多,而且不易出错。例如:
namespace :my_example do
desc "Something"
task :my_task => :environment do
puts ARGV.inspect
end
end
then
然后
rake my_example:my_task 1 2 3
#=> ["my_example:my_task", "1", "2", "3"]
The only thing you need to keep in mind is that ARGV[0] is the process name, so use only ARGV[1..-1].
唯一需要记住的是 ARGV[0] 是进程名称,因此仅使用 ARGV[1..-1]。
I realize that strictly speaking this does not answer the question, as it does not make use of :environment as part of the solution. But OP did not state why he included that stipulation so it might still apply to his use case.
我意识到严格来说这并不能回答问题,因为它没有使用 :environment 作为解决方案的一部分。但是 OP 没有说明为什么他包含该规定,因此它可能仍然适用于他的用例。

