programing

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

bestprogram 2023. 6. 6. 10:21

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

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

이 값을 명령줄 또는 다른 레이크 태스크에서 레이크 태스크로 전달하려고 합니다.

어떻게 해야 하나요?

작업 호출에 기호 인수를 추가하여 형식 인수를 레이크로 지정할 수 있습니다.예:

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

그런 다음 명령줄에서 다음을 수행합니다.

> rake my_task[1, false]클래스 레이크의 인수: {:arg1=>"1", :arg2=>"false"}: 작업 인수arg1은 다음과 같습니다. String의 '1'arg2는 다음과 같습니다. String 클래스의 'false'.
> rake "my_task[1, 2]"인수: {:arg1=>"1", :arg2=>"2"}
> rake invoke_my_task인수: {:arg1=>"1", :arg2=>"2"}
> rake invoke_my_task_2인수: {:arg1=>3, :arg2=>4}
> _disposite[5,6]를 사용한 갈퀴인수: {:arg1=>"5", :arg2=>"6"}
> _로 긁어모으기기본값이 있는 인수: {:arg1=>:default_1, :arg2=>:default_2}
> _brake['x','y']로 긁어모으기기본값이 있는 인수: {:arg1=>"x", :arg2=>y"}

두 번째 예제에서 설명한 것처럼 공백을 사용하려면 대상 이름 주위의 따옴표가 있어야 셸이 공간에서 인수를 분할하지 않습니다.

rake.rb의 코드를 보면, rake는 전제 조건에 대한 인수를 추출하기 위해 작업 문자열을 구문 분석하지 않는 것으로 나타나므로 할 수 없습니다.task :t1 => "dep[1,2]"전제 조건에 대해 다른 인수를 지정하는 유일한 방법은 종속 작업 작업 내에서 명시적으로 호출하는 것입니다.:invoke_my_task그리고.:invoke_my_task_2.

와 같은 . zsh 같 은 셸 는 브 분 을 야 합 니 해 다 리 킷 래 서 일 에 부 와 ▁note 다 니 합 야 ▁the ▁( sh ▁z 해 like : ▁z▁brackets ▁somerake my_task\['arg1'\]

옵션 및 종속성은 어레이 내부에 있어야 합니다.

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에서 Rails를 것이 .=> [:environment]이는 종속 태스크를 설정하는 방법입니다.

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

kch로 답변하는 것 외에도 (댓글을 남기는 방법을 찾지 못했습니다, 죄송합니다):

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

rake mytask var=foo

Rake 파일에서 다음과 같은 ENV 변수로 액세스할 수 있습니다.

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

된 인수 표준 된예수인 (를: 준표명))를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 user:create -- -u test@example.com -p 123

이와 같은 레이크 스크립트를 사용할 수 있는 다른 툴을 찾아야 할 때입니다.

저는 이 두 웹사이트에서 답을 찾았습니다. 매니아와 에임레드.

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

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

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

인수를 전달하려면 다음 세 가지 작업을 수행합니다.

  1. 작업 이름 뒤에 인수 이름을 쉼표로 구분하여 추가합니다.
  2. 다음을 사용하여 종속성을 끝에 놓습니다. => [...]
  3. do 뒤에 |t, args|를 배치합니다. (이 작업의 개체입니다.)

스크립트의 인수에 액세스하려면 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]

will 출력

Hello
Hello
Hello
Hello

다른 작업에서 이 작업을 호출하고 인수를 전달하려면 invoke를 사용합니다.

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

그 다음 명령

rake caller

will 출력

In Caller
hi
hi

다음 코드가 깨지기 때문에 종속성의 일부로 인수를 전달하는 방법을 찾지 못했습니다.

task :caller => :task_name['hi',2]' do
   puts 'In Caller'
end

이 문제를 해결하기 전까지는 인수를 전달하는 방법과 : 환경을 파악할 수 없었습니다.

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

사실 @Nick Desjardins는 완벽하게 대답했습니다.하지만 교육을 위해서: 더러운 접근법을 사용할 수 있습니다: 사용.ENV

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

rake my_task myvar=10
#=> myvar: 10

일반적으로 사용되는 또 다른 옵션은 환경 변수를 전달하는 것입니다.당신의 코드에서 당신은 그것들을 읽습니다.ENV['VAR']그리고 그것들을 바로 전에 통과시킬 수 있습니다.rake 예를 들어 , 예들어

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

저는 단지 달리기를 할 수 있기를 원했습니다.

$ 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 task3IMO는 그럴 가치가 없습니다.그냥 못생긴 것을 사용하세요.rake task[arg1,arg2].

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

DB = ARGV[1]

그런 다음 파일의 맨 아래에 있는 Rake 작업을 스탭합니다(Rake는 해당 인수 이름을 기반으로 작업을 찾습니다).

task :database_name1
task :database_name2

명령줄:

rake mytask db_name

var=foo ENVar 및 작업 인수[blah, blah2] 솔루션보다 더 깔끔합니다.
스텁은 약간 징그럽지만, 일회성 설정인 환경이 몇 개 있다면 그리 나쁘지 않습니다.

namespace :namespace1 do
  task :task1, [:arg1, :arg2, :arg3] => :environment do |_t, args|
    p args[:arg1]
  end
end

부르기

rake namespace1:task1["1","2","3"]

통화 중에 환경을 제공할 필요가 없음

zsh에서 호출을 따옴표로 묶어야 합니다.

rake 'namespace1:task1["1","2","3"]'

기존 인수 스타일로 레이크 작업을 실행하는 방법

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

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

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

명령행에서 작업을 실행할 때 따옴표가 반전되어 표시됩니다.

여기서 제가 보지 못하는 한 가지는 임의적인 주장을 다루는 방법입니다.작업 정의에 나열되지 않은 인수를 전달해도 다음과 같이 액세스할 수 있습니다.args.extras:

task :thing, [:foo] do |task, args|
  puts args[:foo]     # named argument
  puts args.extras    # any additional arguments that were passed
end

인수를 기본 작업으로 전달하려면 다음과 같은 작업을 수행할 수 있습니다.예를 들어, "version"이 당신의 주장이라고 합니다.

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"]

에서 Rake task를 사용하여 할 때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

delayed_job_active_record_threaded_streaded 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"}}

위에서 설명한 대부분의 방법은 최신 버전에서는 사용되지 않을 수 있습니다.최신 가이드는 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

만약 당신이 무엇에 대한 주장 입장이 무엇인지 기억하는 것이 귀찮고 루비 주장 해시와 같은 것을 하고 싶다면.하나의 인수를 사용하여 문자열을 전달한 다음 해당 문자열을 옵션 해시로 정규화할 수 있습니다.

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

제가 생각해낸 것은 다음과 같습니다.

# CLI syntax 
rake sometasks:mytask -- myparam=value
# app/lib/tasks/sometasks.rake

def parse_options
    options = ActiveSupport::HashWithIndifferentAccess.new
    separator_index = ARGV.index("--")
    if separator_index
      option_array = ARGV.slice(separator_index + 1 , ARGV.length)
      option_pairs = option_array.map { |pair| pair.split("=") }
      option_pairs.each { |opt| options[opt[0]] = opt[1] || true }
    end
    options
end

namespace :sometasks do
  task :mytask do 
    options = parse_options
    myparam = options[:myparam]
    # my task ...
  end
end

이를 통해 모든 매개 변수를 전달할 수 있으며, 각 매개 변수에 값이 할당된 경우 여러 레이크 작업을 연속으로 호출하는 동안 작동해야 합니다.

하지만 아마 개선의 여지가 있을 것입니다.

매개 변수를 전달하는 동안에는 입력 파일이 더 좋습니다. 이것이 Excel 아손 또는 필요한 것이 무엇이든 될 수 있습니다. 그리고 필요에 따라 변수 이름을 포함하여 필요한 데이터 구조와 변수를 읽습니다.파일을 읽는 방법은 다음과 같은 구조를 가질 수 있습니다.

  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 

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