Вопрос

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

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

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

Это было полезно?

Решение

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

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.

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

При выполнении задачи из 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"}

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

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

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

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

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

rake mytask var=foo

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

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

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

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

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

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

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

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

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

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

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

Я нашел ответ на этих двух веб-сайтах: Net Maniac и Aimred .

У вас должна быть версия > 0,8 рейка, чтобы использовать эту технику

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

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

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

<Ол>
  • Добавьте имена аргументов после имени задачи, разделенные запятыми.
  • Поместите зависимости в конец, используя: needs = > [...]
  • 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
    

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

    $ 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
    

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

    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 some:task arg1 arg2
    

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

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

    namespace :some do
      task task: :environment do
        arg1, arg2 = ARGV
    
        # your task...
    
        exit
      end
    end
    

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

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

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

    DB = ARGV[1]
    

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

    task :database_name1
    task :database_name2
    

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

    rake mytask db_name
    

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

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

    Он будет работать с граблями " namespace: taskname ['arguments1'] "

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

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

    Пример:

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

    "Строка запроса", являющаяся:

    width=10&height=20
    

    Предупреждение: обратите внимание, что синтаксис следующий rake "mytask[foo=bar]" и НЕТ rake mytask["foo=bar"]

    При разборе внутри задачи rake с использованием 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 в моем отложенный_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"}}
    

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

    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 # заказных-грабли-задача

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

    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
    

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

    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
    

    Для запуска граблей с традиционным стилем аргументов:

    rake task arg1 arg2
    

    А затем используйте:

    task :task do |_, args|
      puts "This is argument 1: #{args.first}"
    end
    

    Добавьте следующий патч rake gem:

    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
    

    Пример json

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

    Исполнение

    rake :name_task 
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top