Как передать аргументы командной строки задаче rake

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

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

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

17 ответов


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

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 является объектом задачи, не очень полезно, если вы не знаете / заботиться о грабли внутренних органов.

РЕЛЬСЫ ПРИМЕЧАНИЕ:

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

  task :work, [:option, :foo, :bar] => [:environment] do |task, args|
    puts "work", args
  end

вы можете указать формальные аргументы в 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"}

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

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

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


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

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

rake mytask var=foo

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

p ENV['var'] # => "foo"

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

$ rake user:create -- --user [email protected] --pass 123

Примечание --, это необходимо для обхода стандартных аргументов рейка. Должен работать с граблями 0.9.x, .

новые грабли изменили свой разбор --, и теперь вы должны убедиться, что он не передан 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 в end гарантирует, что дополнительные аргументы не будут интерпретироваться как задача Rake.

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

 rake user:create -- -u [email protected] -p 123

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


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

вам нужно иметь версию > 0.8 рейка, чтобы использовать эту технику

нормальное описание задачи грабли это:

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

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

  1. добавьте имена аргументов после имени задачи, разделенные запятыми.
  2. поместите зависимости в конец, используя: needs => [...]
  3. место / t, args / после do. (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

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

$ VAR=foo rake mytask

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

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

rake my_task myvar=10
#=> myvar: 10

Я не мог понять, как передать args, а также :environment, пока я не понял это:

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/']

desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end

Я использую обычный аргумент ruby в файле rake:

DB = ARGV[1]

затем я заглушаю задачи rake в нижней части файла (так как rake будет искать задачу на основе этого имени аргумента).

task :database_name1
task :database_name2

командная строка:

rake mytask db_name

это кажется мне чище, чем var=foo ENV var и задачи args[бла, бла] решения.
заглушка немного Дженки, но не слишком плохо, если у вас есть только несколько сред, которые являются одноразовой установкой


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

$ rake some:task arg1 arg2

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

грабли интерпретирует 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].


способов передать аргумент правильно ответили выше. Однако для запуска задачи rake с аргументами существует небольшая техническая сложность в более новой версии rails

Он будет работать с rake " namespace:taskname ['argument1']"

обратите внимание на перевернутые кавычки при выполнении задачи из командной строки.


мне нравится синтаксис "querystring" для передачи аргументов, особенно когда нужно передать много аргументов.

пример:

rake "mytask[width=10&height=20]"

" строка запросов":

width=10&height=20

предупреждение: обратите внимание, что синтаксис rake "mytask[foo=bar]" и не rake mytask["foo=bar"]

при анализе внутри задачи грабли с помощью Rack::Utils.parse_nested_query , мы получим Hash:

=> {"width"=>"10", "height"=>"20"}

(круто то, что вы можете передавать хэши и массивы, подробнее ниже)

вот как этого добиться:

require 'rack/utils'

task :mytask, :args_expr do |t,args|
  args.with_defaults(:args_expr => "width=10&height=10")
  options = Rack::Utils.parse_nested_query(args[:args_expr])
end

вот более расширенный пример, который я использую с Rails в моем delayed_job_active_record_threaded gem:

bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"

проанализирован так же, как и выше, с зависимостью среды (для загрузки среды Rails)

namespace :dj do
  task :start, [ :args_expr ] => :environment do |t, args|
    # defaults here...
    options = Rack::Utils.parse_nested_query(args[:args_expr])  
  end
end

дает следующее options

=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}

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

task :default, [:version] => [:build]

task :build, :version do |t,args|
  version = args[:version]
  puts version ? "version is #{version}" : "no version passed"
end

тогда вы можете назвать это так:

$ rake
no version passed

или

$ rake default[3.2.1]
version is 3.2.1

или

$ rake build[3.2.1]
version is 3.2.1

однако я не нашел способа избежать указания имени задачи (по умолчанию или сборки) при передаче аргументов. Хотел бы услышать, если кто-нибудь знает способ.


большинство методов, описанных выше, не работали для меня, возможно, они устарели в более новых версиях. Современное руководство можно найти здесь:http://guides.rubyonrails.org/command_line.html#custom-rake-tasks

копирование и вставка ans из руководства здесь:

task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
  # You can use args from here
end

вызовите его так

bin/rake "task_name[value 1]" # entire argument string should be quoted

Если вы не можете вспомнить, какая позиция аргумента для чего, и вы хотите сделать что-то вроде хэша аргумента ruby. Вы можете использовать один аргумент для передачи строки, а затем regex эту строку в хэш параметров.

namespace :dummy_data do
  desc "Tests options hash like arguments"
  task :test, [:options] => :environment do |t, args|
    arg_options = args[:options] || '' # nil catch incase no options are provided
    two_d_array = arg_options.scan(/\W*(\w*): (\w*)\W*/)
    puts two_d_array.to_s + ' # options are regexed into a 2d array'
    string_key_hash = two_d_array.to_h
    puts string_key_hash.to_s + ' # options are in a hash with keys as strings'
    options = two_d_array.map {|p| [p[0].to_sym, p[1]]}.to_h
    puts options.to_s + ' # options are in a hash with symbols'
    default_options = {users: '50', friends: '25', colour: 'red', name: 'tom'}
    options = default_options.merge(options)
    puts options.to_s + ' # default option values are merged into options'
  end
end

и в командной строке вы получите.

$ rake dummy_data:test["users: 100 friends: 50 colour: red"]
[["users", "100"], ["friends", "50"], ["colour", "red"]] # options are regexed into a 2d array
{"users"=>"100", "friends"=>"50", "colour"=>"red"} # options are in a hash with keys as strings
{:users=>"100", :friends=>"50", :colour=>"red"} # options are in a hash with symbols
{:users=>"100", :friends=>"50", :colour=>"red", :name=>"tom"} # default option values are merged into options

при передаче параметров, лучше вариант является входным файлом, может ли это быть excel json или все, что вам нужно, и оттуда прочитать структуру данных и переменные, которые вам нужны, включая имя переменной, как это необходимо. Для чтения файл может иметь следующую структуру.

  namespace :name_sapace_task do
    desc "Description task...."
      task :name_task  => :environment do
        data =  ActiveSupport::JSON.decode(File.read(Rails.root+"public/file.json")) if defined?(data)
    # and work whit yoour data, example is data["user_id"]

    end
  end

пример json

{
  "name_task": "I'm a task",
  "user_id": 389,
  "users_assigned": [389,672,524],
  "task_id": 3
}

исполнение

rake :name_task