如何在 Rails 中使用环境将参数传递给 Rake 任务? [复制]
Posted
技术标签:
【中文标题】如何在 Rails 中使用环境将参数传递给 Rake 任务? [复制]【英文标题】:How to pass arguments into a Rake task with environment in Rails? [duplicate] 【发布时间】:2010-11-24 08:46:07 【问题描述】:我可以传递如下参数:
desc "Testing args"
task: :hello, :user, :message do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #args[:user]. #:message"
end
我还能够为 Rails 应用程序加载当前环境
desc "Testing environment"
task: :hello => :environment do
puts "Hello #User.first.name."
end
我想做的是能够拥有变量和环境
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
但这不是一个有效的任务调用。有谁知道我如何做到这一点?
【问题讨论】:
您能否更新以接受inger 的新答案。 【参考方案1】:TLDR;
task :t, [args] => [deps]
原答案
当您将参数传递给 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
根据@Peiniau 下面的评论更新
关于 Rails > 3.1
task :t, arg, :needs => [deps] # deprecated
请使用
task :t, [args] => [deps]
【讨论】:
请注意,最新的文档以这种方式描述:needs
方法:“出于兼容性考虑,仍支持该格式,但不建议使用。” (我只为未来的浏览器提到这一点,因为它表明最终:needs
将不再受支持。该部分称为“不推荐使用的任务参数格式”...)
该代码中的错误:puts "Hello #User.first.name.#:message" ...这不会打印“感谢登录”,只是“消息”。修复:#args.message 最后一个替换。
Rails 3.1 'task :t, arg, :needs => [deps]' 已被弃用。请改用 'task :t, [args] => [deps]'。
用一个例子来澄清前面的评论,我相信这对task :hello, [:message] => [:environment] do |t, args|
来说是可行的。
附加说明:传递多个参数,task :hello, [:message1, :message2] => [:environment] do |t, args|
有效,并调用使用 rake hello['message #1','message #2']
。警告:我发现如果参数列表包含任何明文,rake 会失败,例如rake hello['message #1', 'message #2']
(注意逗号后面的空格)。【参考方案2】:
虽然这些解决方案有效,但我认为这过于复杂。
另外,如果你在 zsh 中这样做,如果你的数组中的括号没有用 '\' 转义,你会得到错误。
我推荐使用 ARGV 数组,它工作得很好,更简单,而且更不容易出错。例如:
namespace :my_example do
desc "Something"
task :my_task => :environment do
puts ARGV.inspect
end
end
然后
rake my_example:my_task 1 2 3
#=> ["my_example:my_task", "1", "2", "3"]
您需要记住的唯一一件事是 ARGV[0] 是进程名称,因此请仅使用 ARGV[1..-1]。
我意识到严格来说这并不能回答问题,因为它没有使用 :environment 作为解决方案的一部分。但是 OP 没有说明他为什么包含该规定,因此它可能仍适用于他的用例。
【讨论】:
:environment
是加载 Rails 应用程序代码所必需的。并在我得到的 Rails 应用程序上尝试:["my_example:my_task", "1", "2", "3"] rake aborted! Don't know how to build task '1' (see --tasks)
这正是我想要的
@Djunzu:是的,我给出的示例参数并不是为了成为 rake 任务的真实输入。这只是为了说明。【参考方案3】:
只是为了跟进这个老话题;这就是我认为当前的 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
这就是你调用它的方式 (http://guides.rubyonrails.org/v4.2/command_line.html#rake):
rake "hello[World]"
对于多个参数,只需将它们的关键字添加到任务声明的数组中(task :hello, [:a,:b,:c]...
),并以逗号分隔传递:
rake "hello[Earth,Mars,Sun,Pluto]"
注意:参数个数没有被检查,所以奇数行星被忽略了:)
【讨论】:
这个答案应该是被接受的。 Man...rake 对我来说总是那么不红。 ruby 中的大多数事情你首先猜测的是它实际上是如何工作的。这种语法很奇怪。 发送 2 个参数,task :hello, [:arg1, :arg2] => :environment do |t, args| 发送 2 个参数,[:arg1,:arg2] 之间没有空格 @hbin 啊,所以这是当你调用 rake 而不是 Rakefile 中的声明(ChaseT. 的评论提到的).. 是的,在这种情况下是 shell 规则,所以你要么写东西作为一个 shell-word(无空格)或引用空格,或在整个内容周围使用引号,例如rake 'webp:convert["hello", "world"]'
.. 警告:我现在还没有尝试过这个,但它应该可以工作。【参考方案4】:
解决此问题的另一种方法:使用操作系统环境变量。这种方法的好处:
所有相关的 rake 任务都可以获得选项。 语法要简单得多,不依赖于难以理解且随时间变化的 rake DSL。我有一个需要三个命令行选项的 rake 任务。这是我调用它的方式:
$ rake eaternet:import country=us region=or agency=multco
这是非常干净、简单的 bash 语法,我喜欢。这是我的 rake 任务。也很干净,没有魔法:
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
此特定示例未显示依赖项的使用。但是如果:import
任务确实依赖于其他人,他们也可以访问这些选项。但是使用正常的 rake options 方法,他们不会。
【讨论】:
这绝对不是环境变量!它 is rake arguments 即使 rake 将其显示为环境变量。存在巨大的概念(和实际)差异!请注意,country=us ruby -e "puts ENV['country']"
与 ruby -e "puts ENV['country']" country=us
不同(第一个中的环境变量与第二个中的参数)。【参考方案5】:
为了完整起见,这里是上面提到的docs 的示例:
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
注意事项:
显然,您可以省略#with_defaults
调用。
您必须使用Array
作为参数,即使只有一个。
先决条件不必是Array
。
args
是 Rake::TaskArguments
的一个实例。
t
是 Rake::Task
的一个实例。
【讨论】:
这解释了为什么args.empty?
给了我奇怪的结果。 args
看起来像一个哈希,但它是一个 Rake::TaskArguments
。因此,如果您希望在未传递任何参数时出现特殊行为,请在检查 args
是否为空之前调用 #to_hash
或 #to_s
。以上是关于如何在 Rails 中使用环境将参数传递给 Rake 任务? [复制]的主要内容,如果未能解决你的问题,请参考以下文章