Как передать аргументы командной строки в задачу rake - PullRequest
1028 голосов
/ 05 мая 2009

У меня есть задача rake, которая должна вставить значение в несколько баз данных.

Я бы хотел передать это значение в задачу rake из командной строки или из другой задачи rake.

Как я могу это сделать?

Ответы [ 18 ]

1107 голосов
/ 05 мая 2009

Вы можете указать формальные аргументы в rake, добавив символьные аргументы к вызову задачи. Например:

require 'rake'

task :my_task, [:arg1, :arg2] do |t, args|
  puts "Args were: #{args}"
end

task :invoke_my_task do
  Rake.application.invoke_task("my_task[1, 2]")
end

# or if you prefer this syntax...
task :invoke_my_task_2 do
  Rake::Task[:my_task].invoke(3, 4)
end

# a task with prerequisites passes its 
# arguments to it prerequisites
task :with_prerequisite, [:arg1, :arg2] => :my_task #<- name of prerequisite task

# to specify default values, 
# we take advantage of args being a Rake::TaskArguments object
task :with_defaults, :arg1, :arg2 do |t, args|
  args.with_defaults(:arg1 => :default_1, :arg2 => :default_2)
  puts "Args with defaults were: #{args}"
end

Затем из командной строки:

> rake my_task[1,2]
Args were: {:arg1=>"1", :arg2=>"2"}

> rake "my_task[1, 2]"
Args were: {:arg1=>"1", :arg2=>"2"}

> rake invoke_my_task
Args were: {:arg1=>"1", :arg2=>"2"}

> rake invoke_my_task_2
Args were: {:arg1=>3, :arg2=>4}

> rake with_prerequisite[5,6]
Args were: {:arg1=>"5", :arg2=>"6"}

> rake with_defaults
Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2}

> rake with_defaults['x','y']
Args with defaults were: {:arg1=>"x", :arg2=>"y"}

Как показано во втором примере, если вы хотите использовать пробелы, кавычки вокруг целевого имени необходимы, чтобы оболочка не разделяла аргументы в пробеле.

Глядя на код в rake.rb , выясняется, что rake не анализирует строки задач для извлечения аргументов для предварительных условий, поэтому вы не можете выполнить task :t1 => "dep[1,2]". Единственный способ указать различные аргументы для предварительного условия - это явно вызвать его в зависимом действии задачи, как в :invoke_my_task и :invoke_my_task_2.

Обратите внимание, что некоторые оболочки (например, zsh) требуют, чтобы вы выходили за скобки: rake my_task\['arg1'\]

313 голосов
/ 19 февраля 2011

В дополнение к ответу по kch (я не нашел, как оставить комментарий к этому, извините):

Вам не нужно указывать переменные как ENV переменные перед командой rake. Вы можете просто установить их как обычные параметры командной строки, например:

rake mytask var=foo

и получите доступ к файлам из вашего файла rake как переменные ENV, например:

p ENV['var'] # => "foo"
308 голосов
/ 08 апреля 2015

параметры и зависимости должны быть внутри массивов:

namespace :thing do
  desc "it does a thing"
  task :work, [:option, :foo, :bar] do |task, args|
    puts "work", args
  end

  task :another, [:option, :foo, :bar] do |task, args|
    puts "another #{args}"
    Rake::Task["thing:work"].invoke(args[:option], args[:foo], args[:bar])
    # or splat the args
    # Rake::Task["thing:work"].invoke(*args)
  end

end

Тогда

rake thing:work[1,2,3]
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}

rake thing:another[1,2,3]
=> another {:option=>"1", :foo=>"2", :bar=>"3"}
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}

ПРИМЕЧАНИЕ: переменная task - это объект задачи, не очень полезный, если вы не знаете / заботитесь о внутренностях Rake.

ПРИМЕЧАНИЕ:

Если вы запускаете задачу из рельсов, лучше всего предварительно загрузить среду, добавив => [:environment], который является способом настройки зависимых задач.

  task :work, [:option, :foo, :bar] => [:environment] do |task, args|
    puts "work", args
  end
103 голосов
/ 19 октября 2013

Если вы хотите передать именованные аргументы (например, со стандартным OptionParser), вы можете использовать что-то вроде этого:

$ rake user:create -- --user test@example.com --pass 123

обратите внимание на --, это необходимо для обхода стандартных аргументов Rake. Должен работать с Rake 0.9.x , <= 10.3.x </strong>.

Более новые Rake изменили свой синтаксический анализ --, и теперь вы должны убедиться, что он не передан методу OptionParser#parse, например, с parser.parse!(ARGV[2..-1])

require 'rake'
require 'optparse'
# Rake task for creating an account

namespace :user do |args|
  desc 'Creates user account with given credentials: rake user:create'
  # environment is required to have access to Rails models
  task :create do
    options = {}
    OptionParser.new(args) do |opts|
      opts.banner = "Usage: rake user:create [options]"
      opts.on("-u", "--user {username}","User's email address", String) do |user|
        options[:user] = user
      end
      opts.on("-p", "--pass {password}","User's password", String) do |pass|
        options[:pass] = pass
      end
    end.parse!

    puts "creating user account..."
    u = Hash.new
    u[:email] = options[:user]
    u[:password] = options[:pass]
    # with some DB layer like ActiveRecord:
    # user = User.new(u); user.save!
    puts "user: " + u.to_s
    puts "account created."
    exit 0
  end
end

exit в конце убедится, что дополнительные аргументы не будут интерпретироваться как задача Rake.

Также должен работать ярлык для аргументов:

 rake user:create -- -u test@example.com -p 123

Когда rake-скрипты выглядят так, возможно, пришло время искать другой инструмент, который позволил бы это прямо из коробки.

58 голосов
/ 05 мая 2009

Я нашел ответ на этих двух сайтах: Чистый маньяк и Aimred .

Для использования этой техники у вас должна быть версия> 0.8 рейка

Обычное описание задачи с граблями:

desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
  #interesting things
end

Чтобы передать аргументы, сделайте три вещи:

  1. Добавьте имена аргументов после имени задачи, разделенные запятыми.
  2. Поместите зависимости в конец, используя: needs => [...]
  3. Place | t, args | после того как (t является объектом для этой задачи)

Чтобы получить доступ к аргументам в сценарии, используйте args.arg_name

desc 'Takes arguments task'
task :task_name, :display_value, :display_times, :needs => [:depends_on_taskA, :depends_on_taskB] do |t, args|
  args.display_times.to_i.times do
    puts args.display_value
  end
end

Чтобы вызвать эту задачу из командной строки, передайте ей аргументы в [] s

rake task_name['Hello',4]

выдаст

Hello
Hello
Hello
Hello

и если вы хотите вызвать эту задачу из другой задачи и передать ей аргументы, используйте invoke

task :caller do
  puts 'In Caller'
  Rake::Task[:task_name].invoke('hi',2)
end

тогда команда

rake caller

выдаст

In Caller
hi
hi

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

task :caller => :task_name['hi',2]' do
   puts 'In Caller'
end
29 голосов
/ 28 февраля 2011

На самом деле @Nick Desjardins ответил отлично. Но только для образования: вы можете использовать грязный подход: использовать ENV аргумент

task :my_task do
  myvar = ENV['myvar']
  puts "myvar: #{myvar}"
end 

rake my_task myvar=10
#=> myvar: 10
29 голосов
/ 05 мая 2009

Другим часто используемым вариантом является передача переменных окружения. В вашем коде вы читаете их через ENV['VAR'] и можете передать их прямо перед командой rake, например

$ VAR=foo rake mytask
27 голосов
/ 29 ноября 2014

Я не мог понять, как передавать аргументы, а также: окружение, пока не решил это:

namespace :db do
  desc 'Export product data'
  task :export, [:file_token, :file_path] => :environment do |t, args|
    args.with_defaults(:file_token => "products", :file_path => "./lib/data/")

       #do stuff [...]

  end
end

А потом я звоню так:

rake db:export['foo, /tmp/']
22 голосов
/ 16 октября 2012
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end
18 голосов
/ 29 апреля 2016

Я просто хотел иметь возможность запустить:

$ rake some:task arg1 arg2

Просто, верно? (Неа!)

Rake интерпретирует arg1 и arg2 как задачи и пытается их запустить. Поэтому мы просто прерываем его до того, как это произойдет.

namespace :some do
  task task: :environment do
    arg1, arg2 = ARGV

    # your task...

    exit
  end
end

Возьми это, скобки!

Отказ от ответственности : Я хотел быть в состоянии сделать это в довольно маленьком домашнем проекте. Не предназначен для использования в "реальном мире", поскольку вы теряете возможность связывать рейк-задачи (т.е. rake task1 task2 task3). ИМО не стоит. Просто используйте уродливый rake task[arg1,arg2].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...