如何在Rails环境中将参数传递给Rake任务?

时间:2009-08-31 14:07:36

标签: ruby-on-rails ruby rake

我能够传递如下参数:

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

但这不是一个有效的任务调用。有谁知道我怎么能做到这一点?

5 个答案:

答案 0 :(得分:362)

只是跟进这个老话题;这就是我认为当前的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]" 

注意:未检查参数的数量,因此遗漏了奇数行星:)

答案 1 :(得分:110)

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] 

答案 2 :(得分:59)

为了完整起见,这里是上面提到的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
  • argsRake::TaskArguments
  • 的一个实例
  • tRake::Task
  • 的一个实例

答案 3 :(得分:18)

另一种解决方法:使用OS环境变量。这种方法的好处:

  • 所有相关的佣金任务都可以获得选项。
  • 语法简单得多,不依赖于很难弄清楚且随时间变化的rake DSL。

我有一个rake任务,需要三个命令行选项。以下是我如何调用它:

$ rake eaternet:import country=us region=or agency=multco

这是非常干净,简单,而且只是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

此特定示例未显示依赖项的使用。但如果:import任务确实取决于其他任务,他们也可以访问这些选项。但是使用普通的rake选项方法,他们不会。

答案 4 :(得分:10)

虽然这些解决方案有效,但我觉得这太复杂了。

另外,如果你在zsh中这样做,如果你的数组中的括号没有用'\'转义,你就会出错。

我建议使用ARGV数组,它工作正常,更简单,并且不容易出错。 E.g:

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]。

我意识到严格来说,这并没有回答这个问题,因为它没有利用:环境作为解决方案的一部分。但是OP没有说明为什么他包含这个规定所以它可能仍然适用于他的用例。