레이크 작업에 명령 행 인수를 전달하는 방법


1096

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

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

어떻게해야합니까?



3
문서 는 SeattleRb에 의해 반영되었습니다.
Jonathan Allard

1
허용 된 답변이 현재 매우 오래되었으므로 @BlairAnderson에서 허용 된 답변을 변경할 수 있습니까? 이 질문은이 주제에 대해 Google에 많이 나타납니다.
rmcsharry

답변:


377

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

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

28
또한 인수 사이에 공백을 사용하지 마십시오. 예를 들어, 이렇게하지 마십시오 : 작동하지 않아 rake thing:work[1, 2, 3]오류가 발생합니다Don't know how to build task
rpbaltazar

9
또한 인수를 문자열로 묶어야합니다. 예를 들어 커맨드 라인에서 레이크 작업을 실행하십시오 rake thing:work'[1,2,3]'
theterminalguy

36
안타깝게도 zsh는 호출을 올바르게 구문 분석 할 수 없으므로 다음과 같이 zsh에 명령을 입력해야합니다. rake thing:work\[1,2,3\]또는 이것rake 'thing:work[1,2,3]'
hutusi

1
@sakurashinken 당신은 :environment당신의 작업 에서 기호를 제거 할 수 있습니다 . 레일 응용 프로그램에는 : 환경 작업이 있습니다 ...
Blair Anderson

3
t의미 를 설명하기 위해 메모를 작성하는 대신 매개 변수 이름으로 task사용하지 않는 이유 task는 무엇입니까?
Joshua Pinter

1132

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

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, 거짓]
Arke : 클래스 Rake :: TaskArguments의 {: arg1 => "1", : arg2 => "false"}
arg1은 다음과 같습니다 : String 클래스의 '1'
arg2는 다음과 같습니다 : String 클래스의 'false'

> "my_task [1, 2]"갈퀴
인수는 {: arg1 => "1", : arg2 => "2"}입니다.

> invoke_my_task 레이크
인수는 {: arg1 => "1", : arg2 => "2"}입니다.

> invoke_my_task_2 갈퀴
인수 : {: arg1 => 3, : arg2 => 4}

> with_prerequisite [5,6] 갈퀴
인수는 {: arg1 => "5", : arg2 => "6"}입니다.

> 레이크 with_defaults
기본값이있는 Args는 {: arg1 => : default_1, : arg2 => : default_2}입니다.

> with_defaults [ 'x', 'y'] 갈퀴
기본값이있는 Args는 {: arg1 => "x", : arg2 => "y"}입니다.

두 번째 예에서 설명했듯이 공백을 사용하려면 셸에서 공백을 인수로 나누지 않도록 대상 이름을 따옴표로 묶어야합니다.

rake.rb 의 코드를 보면 rake가 작업 문자열을 구문 분석하여 전제 조건의 인수를 추출하지 않으므로 수행 할 수없는 것으로 보입니다 task :t1 => "dep[1,2]". 전제 조건에 대해 다른 인수를 지정하는 유일한 방법은 :invoke_my_task및 에서 와 같이 종속 태스크 조치 내에서 명시 적으로 호출하는 것 :invoke_my_task_2입니다.

zsh와 같은 일부 쉘에서는 대괄호를 이스케이프해야합니다. rake my_task\['arg1'\]


5
할 Simpy에 네임 스페이스 내에서 작업을 호출하려면 다음 레이크 :: 작업 [ '네임 스페이스 : 작업'] 호출합니다.
gaqzi

1
그것은 별도의 질문 인 Igoru이지만 호출 한 번만 호출하는 이유는 레이크가 종속성 지향이기 때문에 필요한 경우에만 작업을 실행하기 때문입니다. 일반 작업의 경우 아직 실행되지 않았 음을 의미합니다. 종속성에 관계없이 작업을 명시 적으로 실행하거나 필요한 경우 호출 대신 실행을 호출하십시오.
Nick Desjardins

10
참고 : 레이크에 따르면, 작업에서 변수를 받아들이는이 구문은 더 이상 사용되지 않습니다.WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
Ajedi32

57
zsh가 명령 행 인수를 올바르게 구문 분석하지 못 zsh: no matches found: ...하므로 대괄호를 이스케이프해야합니다 rake my_task\['arg1'\]. 에서 robots.thoughtbot.com/post/18129303042/...
세스 브로

2
@SethBro 예. 귀하의 의견 만 "추가 의견보기"링크 뒤에 숨겨져 있지 않은 경우 10 분 동안이 작업을 수행 할 수 없었습니다.
GMA

342

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

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

rake mytask var=foo

다음과 같은 레이크 파일에서 ENV 변수로 액세스하십시오.

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

2
이것이 가장 간단한 답변 IMO입니다. 바로 작동했습니다. 정확히 무슨 p뜻입니까?
stevec 2016 년

1
@ user5783745 puts와 같지만 value.to_s를 표준 출력에 기록하는 대신 Obj.inspect를 호출하고 표준 출력에 기록합니다. ruby-doc.org/core-2.0.0/Kernel.html#method-ip
kqcef

환경 변수를 재정의합니까? 환상적인!
Damien Roche

Rake는 완전히 과도하게 엔지니어링 된 혼란이며 이것이 작동 한 유일한 방법입니다. 그리고 그것은 단지 나만이 아닙니다.이 답변은 "올바른"답변과 같은 정도의 투표권을 가지고 있습니다.
lzap

108

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

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

주의 --표준 레이크 인수를 우회 필요하다고. Rake 0.9.x , <= 10.3.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 마지막에 추가 인수가 레이크 작업으로 해석되지 않도록합니다.

또한 인수 바로 가기가 작동해야합니다.

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

레이크 스크립트가 다음과 같이 보일 때, 즉시 사용할 수있는 다른 도구를 찾아야 할 때가 있습니다.


13
내 관점에서 이것은 정말 최고의 답변입니다. 환경 변수 kludge를 무시하고, 작업 인수와 함께 이상한 구문을 사용하면 standard에 대한 추가 이점이 있습니다 --option-names. 내 유일한 제안은 사용하는 것 exit보다는 abort같은 abort쉘 1의 리턴 코드로 당신을 떠날 것입니다. 레이크 작업이 상위 레벨 스크립트의 일부인 경우 0이 아닌 종료가 일종의 오류라고 가정하는 것이 더 일반적입니다.
Joe

1
나는 Joe에게 동의합니다. 이것이 최선의 대답입니다. 당연한 것은 옵션을 스크립트에 전달할 때와 같은 옵션을 전달하기 위해 동일한 인터페이스를 사용하는 것입니다.
Rik Smith-Unna

1
이것이 최선의 답변이라는 데 동의합니다. 못생긴 것을 우회 할 수있는 방법이 --없습니까? rake실제 작업이나 다른 것에 인수를 전달하는 것처럼 ? 좋아하는 task :my_task, :*args do |t, args|것?
Augustin Riedinger

1
게다가, 나는 {username}여기에 무엇이 있는지 이해하지 못합니다 . 어디에 사용됩니까? 왜 거기에 -u {username}없습니까? 건배
Augustin Riedinger

2
Rake가 ARGV를 구문 분석하는 방식은에서 변경되어 10.4.1되돌아갔습니다 10.4.2. github.com/ruby/rake/commit/…
Tombart

58

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

15
이 경고의 상태에 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
따라이

29

일반적으로 사용되는 다른 옵션은 환경 변수를 전달하는 것입니다. 코드에서을 통해 읽고 ENV['VAR'], rake명령 바로 앞에 전달할 수 있습니다.

$ VAR=foo rake mytask

솔직히 나는 갈퀴 작업 (이것은 --go-to-a 프로그램)을 원하고 있었고 내 작업은 ARGV에서 얻을 수 있습니다. 불행히도 이것이 가능한지 확실하지 않지만 현재 귀하의 솔루션을 사용하고 있습니다 : rake var1 = val1 var2 = val2
JasonSmith

3
@ jhs : rake blah -- --these --go --to --a-program( --레이크에 스위치가 종료되었음을 알리려면 stackoverflow.com/questions/5086224/를
mu는 너무 짧습니다.

28

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

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

rake my_task myvar=10
#=> myvar: 10

27

내가 이것을 해결할 때까지 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/']

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

이것을 부르려면 :rake task_name[hello, world]
Dex

2
from rake.rubyforge.org/files/doc/rakefile_rdoc.html "몇 가지주의 할 점이 있습니다. 레이크 작업 이름과 해당 인수는 레이크를위한 단일 명령 행 인수 여야합니다. 일반적으로 공백이 없습니다. 공백이 필요한 경우 그런 다음 rake + argument 문자열 전체를 인용해야합니다. rake "name [billy bob, smith]" "
Gayle

19

방금 달리기를 원했습니다.

$ 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].


3
_, arg1, arg2 = ARGV첫 번째 인수가 레이크 작업의 이름으로 여겨지 면서 이것을 확인해야 했습니다. 그러나 그것은 exit깔끔한 트릭입니다.
지방

rake task[arg1,arg2] && rake task2 && rake task3그보다 못생긴 지 확실하지 않습니다 rake task[arg1,arg2] task2 task3. 아마 효율이 떨어질 것입니다.
Nuclearman

_, *args = ARGV모든 후속 인수를 캡처하는 데 적합합니다! 고마워요!
XtraSimplicity

12

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

DB = ARGV[1]

그런 다음 파일 맨 아래에서 레이크 작업을 스텁 아웃합니다 (레이크가 해당 인수 이름을 기반으로 작업을 찾기 때문에).

task :database_name1
task :database_name2

명령 줄 :

rake mytask db_name

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


2
고정 된 문자열 문제를 방지하려면 dup끝에 사용 하십시오. db = ARGV [1] .dup
Juanda

db = ARGV[1].dup unless ARGV[1].nil?nil을 두는 예외를 방지하는 것이 좋습니다 .
Andre Figueiredo

5

위의 답변에서 인수를 전달하는 방법이 정확합니다. 그러나 인수로 레이크 작업을 실행하려면 최신 버전의 레일에 약간의 기술이 필요합니다

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

명령 행에서 태스크를 실행할 때 역 따옴표를 참고하십시오.


3

기본 작업에 인수를 전달하려면 다음과 같이하십시오. 예를 들어, "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

그러나 인수를 전달하는 동안 작업 이름 (기본값 또는 빌드)을 지정하지 않는 방법을 찾지 못했습니다. 누군가 방법을 알고 있다면 듣고 싶습니다.


3

전달할 인수가 많을 때 인수 전달에 대한 "querystring"구문이 마음에 듭니다.

예:

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

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

width=10&height=20

경고 : 메모를 구문이되어 rake "mytask[foo=bar]"NOT 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

다음은 delayed_job_active_record_threaded gem 에서 Rails와 함께 사용하는 더 확장 된 예입니다 .

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

레일스 환경을로드하기 위해 환경 의존성을 사용하여 위와 동일한 방식으로 구문 분석했습니다.

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

3

어떤 인수 위치가 무엇인지 기억하고 귀찮은 경우 루비 인수 해시와 같은 것을 원합니다. 하나의 인수를 사용하여 문자열을 전달한 다음 해당 문자열을 옵션 해시로 정규화 할 수 있습니다.

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

1
코드에는 빈 줄이 몇 개 있어야합니다. 나는 당신이 그 벽을 읽는 법을 모른다.
Joshua Pinter

2

위에서 설명한 대부분의 방법은 저에게 효과적이지 않았으며 최신 버전에서는 더 이상 사용되지 않을 수 있습니다. 최신 안내서는 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

1

전통적인 인수 스타일로 레이크 작업을 실행하려면 :

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

-5

매개 변수를 전달하는 동안 더 나은 옵션은 입력 파일입니다. 이는 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 

4
Rake 작업에 JSON 지침 파일이 필요한 경우 Rake 작업에서 너무 많은 작업을 수행하고있을 것입니다.
ZiggyTheHamster

이것은 매우 간단한 것을 지나치게 복잡하게 만드는 방법 입니다.
jeffdill2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.