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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:41:39  来源:igfitidea点击:

How to pass arguments into a Rake task with environment in Rails?

ruby-on-railsrubyrake

提问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 of Rake::TaskArguments.
  • tis an instance of Rake::Task.
  • #with_defaults显然,您可以省略调用。
  • 您必须使用 anArray作为您的参数,即使只有一个。
  • 先决条件不需要是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 没有说明为什么他包含该规定,因此它可能仍然适用于他的用例。