your programing

레이크 태스크에 명령 줄 인수를 전달하는 방법

lovepro 2020. 9. 27. 13:31
반응형

레이크 태스크에 명령 줄 인수를 전달하는 방법


여러 데이터베이스에 값을 삽입해야하는 레이크 작업이 있습니다.

이 값을 명령 줄 또는 다른 레이크 작업 에서 레이크 작업으로 전달하고 싶습니다 .

어떻게 할 수 있습니까?


옵션 및 종속성은 배열 내에 있어야합니다.

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에서 형식 인수를 지정할 수 있습니다. 예를 들면 :

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]
인수 : {: arg1 => "1", : arg2 => "2"}

> "my_task [1, 2]"레이크
인수 : {: arg1 => "1", : arg2 => "2"}

> 레이크 invoke_my_task
인수 : {: arg1 => "1", : arg2 => "2"}

> 레이크 invoke_my_task_2
인수 : {: arg1 => 3, : arg2 => 4}

> rake with_prerequisite [5,6]
인수 : {: arg1 => "5", : arg2 => "6"}

> rake with_defaults
기본값이있는 인수 : {: arg1 => : default_1, : arg2 => : default_2}

> rake with_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'\]


kch의 답변 외에도 (나는 그것에 대한 의견을 남기는 방법을 찾지 못했습니다, 죄송합니다) :

명령 ENV전에 변수를 변수 로 지정할 필요가 없습니다 rake. 다음과 같이 일반적인 명령 줄 매개 변수로 설정할 수 있습니다.

rake mytask var=foo

레이크 파일에서 다음과 같은 ENV 변수로 액세스합니다.

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

명명 된 인수 (예 : standard 사용 OptionParser) 를 전달 하려면 다음과 같이 사용할 수 있습니다.

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

주의 --표준 레이크 인수를 우회 필요하다고. Rake 0.9.x , <= 10.3.x 와 함께 작동해야합니다 .

Newer 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

레이크 스크립트가 이렇게 생겼을 때,이 기능을 즉시 사용할 수있는 다른 도구를 찾아야 할 때입니다.


Net ManiacAimred라는 두 웹 사이트에서 답을 찾았 습니다 .

이 기술을 사용하려면 0.8 이상의 레이크 버전이 필요합니다.

일반적인 레이크 작업 설명은 다음과 같습니다.

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

인수를 전달하려면 다음 세 가지를 수행하십시오.

  1. 태스크 이름 뒤에 인수 이름을 쉼표로 구분하여 추가하십시오.
  2. : needs => [...]를 사용하여 종속성을 끝에 넣으십시오.
  3. 장소 | 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

나는 이것을 해결하기 전까지 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

나는 단지 실행할 수 있기를 원했습니다.

$ 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). IMO는 그만한 가치가 없습니다. 그냥 못생긴 rake task[arg1,arg2].


레이크 파일에서 일반 루비 인수를 사용합니다.

DB = ARGV[1]

그런 다음 파일 맨 아래에있는 rake 작업을 스텁 처리합니다 (rake가 해당 인수 이름을 기반으로 작업을 찾으므로).

task :database_name1
task :database_name2

명령 줄 :

rake mytask db_name

이것은 var = foo ENV var 및 task args [blah, blah2] 솔루션보다 나에게 더 깨끗하다고 ​​느낍니다.
스텁은 약간 젠키하지만 일회성 설정 인 몇 가지 환경 만있는 경우에는 그리 나쁘지 않습니다.


인수를 전달하는 방법은 위의 답변에서 정확합니다. 그러나 인수를 사용하여 레이크 작업을 실행하려면 최신 버전의 레일과 관련된 작은 기술이 있습니다.

레이크 "namespace : taskname [ 'argument1']"과 함께 작동합니다.

명령 줄에서 작업을 실행할 때 반전 된 따옴표에 유의하십시오.


특히 전달할 인수가 많을 때 인수 전달을위한 "querystring"구문을 좋아합니다.

예:

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

"querystring"은 다음과 같습니다.

width=10&height=20

경고 : 메모를 구문이되어 rake "mytask[foo=bar]"NOT rake mytask["foo=bar"]

을 사용하여 rake 작업 내부에서 구문 분석하면 다음 Rack::Utils.parse_nested_query을 얻습니다 Hash.

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

(The cool thing is that you can pass hashes and arrays, more below)

This is how to achieve this:

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

Here's a more extended example that I'm using with Rails in my 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]"

Parsed the same way as above, with an environment dependency (in order load the Rails environment)

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

Gives the following in options

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

To pass arguments to the default task, you can do something like this. For example, say "version" is your argument:

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

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

Then you can call it like so:

$ rake
no version passed

or

$ rake default[3.2.1]
version is 3.2.1

or

$ rake build[3.2.1]
version is 3.2.1

However, I have not found a way to avoid specifying the task name (default or build) while passing in arguments. Would love to hear if anyone knows of a way.


Most of the methods described above did not work for me, maybe they are deprecated in the newer versions. The up-to-date guide can be found here: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks

a copy-and-paste ans from the guide is here:

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

Invoke it like this

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

If you can't be bothered to remember what argument position is for what and you want do something like a ruby argument hash. You can use one argument to pass in a string and then regex that string into an options hash.

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

And on the command line you get.

$ 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

To run rake tasks with traditional arguments style:

rake task arg1 arg2

And then use:

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

Add following patch of 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

While passing parameters, it is better option is an input file, can this be a excel a json or whatever you need and from there read the data structure and variables you need from that including the variable name as is the need. To read a file can have the following structure.

  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

Example json

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

Execution

rake :name_task 

참고URL : https://stackoverflow.com/questions/825748/how-to-pass-command-line-arguments-to-a-rake-task

반응형