如何将参数传递到带有Rails环境的Rake任务中?(复制)

时间:2022-05-31 22:27:41

This question already has an answer here:

这个问题已经有了答案:

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?

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

5 个解决方案

#1


104  

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] 

#2


349  

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:)

注意:参数的数量没有被检查,所以这个奇怪的行星被遗漏了:)

#3


55  

Just for completeness, here the example from the docs mentioned 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_defaults call, obviously.
  • 显然,您可以省略#with_defaults调用。
  • You have to use an Array for your arguments, even if there is only one.
  • 您必须为您的参数使用数组,即使只有一个。
  • The prerequisites do not need to be an Array.
  • 先决条件不需要是数组。
  • args is an instance of Rake::TaskArguments.
  • args是Rake的一个实例:TaskArguments。
  • t is an instance of Rake::Task.
  • t是Rake::Task的一个实例。

#4


17  

An alternate way to go about this: use OS environment variables. Benefits of this approach:

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

  • All dependent rake tasks get the options.
  • 所有依赖的rake任务都获得了选项。
  • The syntax is a lot simpler, not depending on the rake DSL which is hard to figure out and changes over time.
  • 语法要简单得多,不依赖于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语法,我喜欢这样。这是我的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

This particular example doesn't show the use of dependencies. But if the :import task did depend on others, they'd also have access to these options. But using the normal rake options method, they wouldn't.

这个特定的示例没有显示依赖项的使用。但是,如果:import任务确实依赖于其他任务,那么它们也可以访问这些选项。但是使用普通的rake options方法,它们不会。

#5


6  

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.

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

#1


104  

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] 

#2


349  

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:)

注意:参数的数量没有被检查,所以这个奇怪的行星被遗漏了:)

#3


55  

Just for completeness, here the example from the docs mentioned 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_defaults call, obviously.
  • 显然,您可以省略#with_defaults调用。
  • You have to use an Array for your arguments, even if there is only one.
  • 您必须为您的参数使用数组,即使只有一个。
  • The prerequisites do not need to be an Array.
  • 先决条件不需要是数组。
  • args is an instance of Rake::TaskArguments.
  • args是Rake的一个实例:TaskArguments。
  • t is an instance of Rake::Task.
  • t是Rake::Task的一个实例。

#4


17  

An alternate way to go about this: use OS environment variables. Benefits of this approach:

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

  • All dependent rake tasks get the options.
  • 所有依赖的rake任务都获得了选项。
  • The syntax is a lot simpler, not depending on the rake DSL which is hard to figure out and changes over time.
  • 语法要简单得多,不依赖于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语法,我喜欢这样。这是我的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

This particular example doesn't show the use of dependencies. But if the :import task did depend on others, they'd also have access to these options. But using the normal rake options method, they wouldn't.

这个特定的示例没有显示依赖项的使用。但是,如果:import任务确实依赖于其他任务,那么它们也可以访问这些选项。但是使用普通的rake options方法,它们不会。

#5


6  

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.

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