Как передать аргументы в задачу Rake с средой в Rails?

Я могу передать аргументы следующим образом:

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

Но это недействительный вызов задачи. Кто-нибудь знает, как я могу это достичь?

Ответ 1

Когда вы передаете аргументы для задач 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

Просто следить за этой старой темой; вот что я думаю, что текущий 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]" 

Примечание: количество аргументов не проверяется, поэтому нечетная планета не учитывается:)

Ответ 3

Просто для полноты, вот пример из 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.

Ответ 4

Альтернативный способ сделать это: использовать переменные среды ОС. Преимущества такого подхода:

  • Все зависимые задачи грабли получают параметры.
  • Синтаксис намного проще, не зависящий от грабли 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, они бы этого не сделали.

Ответ 5

Хотя эти решения работают, на мой взгляд, это слишком сложно.

Кроме того, если вы сделаете это так в 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].

Я понимаю, что, строго говоря, это не отвечает на вопрос, так как он не использует: среду как часть решения. Но ОП не указал, почему он включил это условие, чтобы он мог по-прежнему применяться к его прецеденту.