У мене є задача граблі, якій потрібно вставити значення в декілька баз даних.
Я хотів би передати це значення в завдання рейку з командного рядка або з іншого завдання грабля.
Як я можу це зробити?
У мене є задача граблі, якій потрібно вставити значення в декілька баз даних.
Я хотів би передати це значення в завдання рейку з командного рядка або з іншого завдання грабля.
Як я можу це зробити?
Відповіді:
параметри та залежності повинні бути всередині масивів:
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
rake thing:work[1, 2, 3]
оскільки він не працюватиме, ви отримаєте помилкуDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
або цеrake 'thing:work[1,2,3]'
:environment
символ зі свого завдання. програми для рейок мають: завдання з навколишнього середовища ...
t
означає task
, чому б не просто використовувати task
як ім'я парам?
Ви можете вказати формальні аргументи в рейку, додавши символьні аргументи до виклику завдання. Наприклад:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args} of class #{args.class}"
puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"
puts "arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"
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
Потім з командного рядка:
> граблі my_task [1, помилково] Аргументи були: {: arg1 => "1",: arg2 => "false"} класу Rake :: TaskArguments arg1 було: '1' класу String arg2 було: "false" класу String > граблі "my_task [1, 2]" Аргументи були: {: arg1 => "1",: arg2 => "2"} > граблі invoke_my_task Аргументи були: {: arg1 => "1",: arg2 => "2"} > граблі invoke_my_task_2 Аргументи були: {: arg1 => 3,: arg2 => 4} > граблі з_вимогою [5,6] Аргументи були: {: arg1 => "5",: arg2 => "6"} > граблі з_defaults Аргументи з типовими значеннями були: {: arg1 =>: default_1,: arg2 =>: default_2} > граблі з_defaults ['x', 'y'] Аргументи з типовими значеннями були: {: arg1 => "x",: arg2 => "y"}
Як показано у другому прикладі, якщо ви хочете використовувати пробіли, лапки навколо назви цілі необхідні, щоб оболонка не розщеплювала аргументи на пробіл.
Переглядаючи код у rake.rb , виявляється, що rake не розбирає рядки завдань для вилучення аргументів для передумов, тому ви не можете цього зробити task :t1 => "dep[1,2]"
. Єдиним способом вказати різні аргументи для необхідної умови було б явно викликати його в межах залежної дії завдання, як у :invoke_my_task
і :invoke_my_task_2
.
Зауважте, що деякі снаряди (наприклад, zsh) вимагають від вас вийти з дужок: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), так що вам потрібно , щоб уникнути дужки: rake my_task\['arg1'\]
. З сайту robots.thoughtbot.com/post/18129303042/…
Крім відповіді від kch (я не знайшов, як залишити коментар до цього, вибачте):
Не потрібно вказувати змінні як ENV
змінні перед rake
командою. Ви можете просто встановити їх як звичайні параметри командного рядка:
rake mytask var=foo
і отримуйте доступ до таких файлів з вашого грабля, як ENV-змінних, таких як:
p ENV['var'] # => "foo"
p
означає?
Якщо ви хочете передати названі аргументи (наприклад, зі стандартними OptionParser
), ви можете використовувати щось подібне:
$ rake user:create -- --user test@example.com --pass 123
Зауважте --
, це необхідно для обходу стандартних аргументів Rake. Повинно працювати з Rake 0.9.x , <= 10.3.x .
Новіші 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
Коли сценарії граблі виглядають так, можливо, саме час шукати інший інструмент, який би дозволив це просто вийти з поля.
--option-names
. Моя єдина пропозиція буде використовувати, exit
а не abort
як, abort
ви залишите код із зворотним кодом 1 у оболонці. Якщо завдання граблі є частиною сценарію вищого рівня, частіше вважати, що ненульовий вихід - це певна помилка.
--
? Начебто передавати rake
аргументи на власне завдання чи щось? Як, task :my_task, :*args do |t, args|
чи щось?
{username}
тут. Де він використовується? Чому його там немає -u {username}
? Ура
Я знайшов відповідь з цих двох веб-сайтів: Net Maniac та Aimred .
Для використання цієї методики потрібно мати версію> 0,8 граблі
Нормальний опис завдання граблі такий:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Для передачі аргументів виконайте три дії:
Для доступу до аргументів у скрипті використовуйте 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
і якщо ви хочете викликати це завдання з іншого завдання та передавати йому аргументи, використовуйте виклик
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
'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
Інший часто використовуваний варіант - передавати змінні середовища. У своєму коді ви читаєте їх через ENV['VAR']
, і можете передавати їх безпосередньо перед rake
командою, як-от
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(зауважте, --
щоб сказати рейку, що його перемикачі закінчилися), див. stackoverflow.com/questions/5086224/…
Я не міг зрозуміти, як передавати аргументи, а також: середовище, поки я не розробив це:
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
rake task_name[hello, world]
Я просто хотів мати можливість бігати:
$ 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]
.
_, arg1, arg2 = ARGV
так, як перший аргумент бачив назву завдання граблі. Але exit
це акуратний трюк.
rake task[arg1,arg2] && rake task2 && rake task3
Не впевнений, що це менше , ніж некрасиво rake task[arg1,arg2] task2 task3
. Напевно, менш ефективно.
_, *args = ARGV
ідеально підходить для збору всіх наступних аргументів! Дякую купи!
Я використовую звичайний аргумент рубіна у файлі граблі:
DB = ARGV[1]
то я заглублюю завдання граблів у нижній частині файлу (оскільки рейка шукатиме завдання на основі цього аргументу).
task :database_name1
task :database_name2
командний рядок:
rake mytask db_name
для мене це чистіше, ніж var = foo ENV var та рішення аргументів [bla, blah2].
заглушка трохи прискіплива, але не дуже погана, якщо у вас просто кілька середовищ, які є одноразовими настройками
dup
в кінці: дБ = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
запобігти виключенню копіювання нуля.
Способи передачі аргументу правильні у наведеній вище відповіді. Однак для запуску рейкової задачі з аргументами, в новій версії рейок є невеликий технічний рівень
Він буде працювати з граблім "простір імен: taskname ['argument1']"
Зверніть увагу на перевернуті лапки при виконанні завдання з командного рядка.
Для передачі аргументів до завдання за замовчуванням ви можете зробити щось подібне. Наприклад, скажіть "версія" - ваш аргумент:
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
Однак я не знайшов способу уникнути вказівки імені завдання (за замовчуванням або збірки) під час передачі аргументів. Мені хотілося б почути, якщо хтось знає спосіб.
Мені подобається синтаксис "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 :
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"}}
Якщо ви не можете турбуватися, щоб згадати, яка позиція аргументу для чого, і ви хочете зробити щось на зразок хеш-аргументу рубіну. Ви можете використовувати один аргумент, щоб передати рядок, а потім переробити цей рядок у хеш параметрів.
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
Більшість описаних вище методів для мене не працювали, можливо, вони застаріли в новіших версіях. Оновлений посібник ви можете знайти тут: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
скопіюйте та вставте анс із посібника тут:
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
Для виконання завдань граблі в традиційному стилі аргументів:
rake task arg1 arg2
А потім скористайтеся:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Додайте наступний патч з дорогоцінним каменем:
Rake::Application.class_eval do
alias origin_top_level top_level
def top_level
@top_level_tasks = [top_level_tasks.join(' ')]
origin_top_level
end
def parse_task_string(string) # :nodoc:
parts = string.split ' '
return parts.shift, parts
end
end
Rake::Task.class_eval do
def invoke(*args)
invoke_with_call_chain(args, Rake::InvocationChain::EMPTY)
end
end
Під час передачі параметрів кращим варіантом є вхідний файл, чи може це бути 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
{
"name_task": "I'm a task",
"user_id": 389,
"users_assigned": [389,672,524],
"task_id": 3
}
rake :name_task