980

複数のデータベースに値を挿入する必要があるレーキタスクがあります。

この値をコマンドラインから、またはから直接rakeタスクに渡したいのですが。別のレーキタスク

これどうやってするの?


  • rakefileのrdoc - Brian Maltzan
  • ドキュメントSeattleRbによってミラーリングされています。 - Jonathan Allard
  • 承認された回答は現在非常に古くなっているため、承認された回答を@BlairAndersonからのものに変更してください。この質問はこのトピックに関してGoogleで高く評価されています。 - rmcsharry

17 답변


264

オプションと依存関係は配列の中にある必要があります。

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


  • これは2016年8月にmのために働いた...更新された答えはこれに更新されるべきだと思います! - rmcsharry
  • 私はこれを更新して、要求による答えとして受け入れられるようにしました。ただし、タスク自体から別のレーキタスクに引数を渡す方法については説明していません。 - Tilendor
  • また、引数の間にスペースを入れないでください。例:これをしないでください。rake thing:work[1, 2, 3]正常に機能しなかったため、エラーが発生しますDon't know how to build task - rpbaltazar
  • また、引数を必ず文字列で囲んでください。例:コマンドラインからrakeタスクを実行するrake thing:work'[1,2,3]' - Damian Simon Peter
  • 残念ながら、zshは呼び出しを正しく解析できません。zshで次のようにコマンドを入力する必要があります。rake thing:work\[1,2,3\]またはこれrake 'thing:work[1,2,3]' - hutusi

1093

タスク呼び出しにシンボル引数を追加することで、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"}

2番目の例で示したように、スペースを使用する場合は、シェルがスペースで引数を分割しないようにするために、ターゲット名を囲む引用符が必要です。

のコードを見るrake.rbrakeはタスク文字列を解析して前提条件の引数を抽出することはしていないようです。task :t1 => "dep[1,2]"。前提条件に異なる引数を指定する唯一の方法は、次のように依存タスクのアクション内で明示的に呼び出すことです。:invoke_my_taskそして:invoke_my_task_2

(zshのような)いくつかのシェルでは角括弧をエスケープする必要があることに注意してください。rake my_task\['arg1'\]


  • ネームスペース内のタスクを単純に呼び出すには、次のようにします。Rake :: Task [&#39; namespace:task&#39;]。invoke - gaqzi
  • それは別の質問、Igoruですが、あなたのinvoke呼び出しが一度だけ実行されるのは、rakeは依存志向であるため、必要な場合にのみタスクを実行するからです。一般的なタスクの場合は、まだ実行されていない場合依存関係に関係なく、または必要であればタスクを明示的に実行するには、invokeではなくexecuteを呼び出します。 - Nick Desjardins
  • 注:rake氏によると、タスク内で変数を受け入れるためのこの構文は推奨されていません。WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead. - Ajedi32
  • zshがコマンドライン引数を正しく解析できないことに注意してください(zsh: no matches found: ...)なので、角括弧をエスケープする必要があります。rake my_task\['arg1'\]。からrobots.thoughtbot.com/post/18129303042/… - Seth Bro
  • @ SethBroはい。自分のコメントのみが[他のコメントを表示]の後ろに隠れていない場合リンクこの作品を完成させることが不可能な10分を無駄にしなかったでしょう。 - GMA

303

kchによる回答に加えて(コメントを残す方法がわかりませんでした、申し訳ありません)。

次のように変数を指定する必要はありません。ENVの前の変数rakeコマンド。そのような通常のコマンドラインパラメータとしてそれらを単に設定することができます:

rake mytask var=foo

そして、以下のようなENV変数としてあなたのレーキファイルからそれらにアクセスします。

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


  • 本当に便利です。ありがとうございます。 - Hoang Le
  • ああ、そうこのそれがRailsのやり方です。意味があります... - Ajedi32

99

名前付き引数を渡したい場合OptionParser)あなたはこのようなものを使うことができます:

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

に注意してください--、それは標準的なRake引数を迂回するために必要です。 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タスクとして解釈されないようにします。

引数のショートカットも機能するはずです。

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

すくいスクリプトがこのように見えるとき、多分それは箱から出してすぐこれを可能にするだろう別のツールを探す時が来たかもしれません。


  • 私の見解では、これは本当に良い答えです。環境変数kludges、タスク引数を持つ奇妙な構文、標準の追加の利点を回避する--option-names。私の唯一の提案は使用することでしょうexitのではなくabortとしてabort戻りコード1がシェルに返されます。レーキタスクが上位レベルのスクリプトの一部である場合、ゼロ以外の終了を想定するのが一般的なエラーです。 - Joe
  • 私はJoeに同意します、これが最良の答えです。当然のことですが、オプションをスクリプトに渡すときと同じインターフェイスを使ってオプションをrakeに渡します。 - Rik Smith-Unna
  • 私はこれが最善の答えだと思います。醜いものを回避する方法はありません--?通り過ぎるようにrake実際のタスクへの引数か何か?好きtask :my_task, :*args do |t, args|か何か? - Augustin Riedinger
  • その上、私は何を理解していないのか{username}ここにあります。どこで使われていますか?なぜそこにないの?-u {username}?乾杯 - Augustin Riedinger
  • RakeがARGVを解析する方法がに変更されました10.4.1そして元に戻った10.4.2github.com/ruby/rake/commit/… - Tombart

56

私はこれら二つのウェブサイトから答えを見つけました:ネットマニアックそして狙った

あなたはこのテクニックを使うためにrakeのバージョン> 0.8を持っている必要があります。

通常のレーキタスクの説明は次のとおりです。

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

引数を渡すには、3つのことをしてください。

  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

このタスクをコマンドラインから呼び出すには、[]に引数を渡します。

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


  • この機能の形式は、次の警告に従って変更されています。'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead. - madh

30

もう1つの一般的に使用されるオプションは環境変数を渡すことです。あなたのコードではENV['VAR']そして、それらの前にそれらを渡すことができますrakeのようなコマンド

$ VAR=foo rake mytask


  • 率直に言って、私はレーキタスクを望んでいました - これらの--go --to -aプログラムと私のタスクはARGVからそれらを得ることができました。残念ながら、それが可能かどうかわかりませんが、現在あなたのソリューションを使用しています:rake var1 = val1 var2 = val2 - JasonSmith
  • @jhs:rake blah -- --these --go --to --a-program(注意してください--スイッチが終了したことをrakeに伝えるには、を参照してください。stackoverflow.com/questions/5086224/… - mu is too short

30

実は@Nick Desjardinsさんは完璧に答えました。しかし教育だけのために:あなたは汚いアプローチを使うことができます:使うことENV引数

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

rake my_task myvar=10
#=> myvar: 10


24

これを解決するまでは、引数と:環境を渡す方法を理解できませんでした。

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
  • からrake.rubyforge.org/files/doc/rakefile_rdoc.html「ほんの数語の注意。レーキタスク名とその引数はrakeへの単一のコマンドライン引数である必要があります。これは通常スペースがないことを意味します。スペースが必要な場合は、rake +引数の文字列全体を引用符で囲む必要があります。このような何か:すくい&quot; name [billy bob、smith]&quot; &quot; - Gayle

16

実行できるようにしたかっただけです。

$ 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 task3) IMOは価値がない。ただ醜いrake task[arg1,arg2]


  • これを作るために必要_, arg1, arg2 = ARGV最初の引数がレーキタスクの名前であると見られていたように。でもあのexitきちんとしたトリックです。 - fatty
  • rake task[arg1,arg2] && rake task2 && rake task3それがより醜いのかどうかわからないrake task[arg1,arg2] task2 task3。しかしおそらく効率が悪いでしょう。 - Nuclearman
  • _, *args = ARGV後続のすべての引数を取り込むのに最適です。どうもありがとうございます。 - XtraSimplicity

13

私はrakeファイルで通常のruby引数を使います。

DB = ARGV[1]

それから私はファイルの一番下にレーキタスクを書き出します(レーキはその引数名に基づいてタスクを探すので)。

task :database_name1
task :database_name2

コマンドライン:

rake mytask db_name

これはvar = foo ENV varやtask args [blah、blah2]の解よりも私にはきれいに感じます。

スタブは少しぎくしゃくしていますが、1回限りのセットアップである環境がいくつかある場合はそれほど悪くありません。


  • フリーズした文字列の問題を防ぐために、dup最後に:db = ARGV [1] .dup - Juanda
  • イベントより良いdb = ARGV[1].dup unless ARGV[1].nil?nilの重複の例外を防ぐため。 - Andre Figueiredo

5

議論を渡す方法は上記の答えで正しいです。しかしながら、引数を付けてrakeタスクを実行するためには、新しいバージョンのrailsに小さな技術が必要です。

それはレーキ "namespace:taskname ['argument1']"で動作します。

コマンドラインからタスクを実行する際の逆引用符に注意してください。


4

私は引数を渡すための "クエリ文字列"構文が好きです、特に渡すべき引数がたくさんあるとき。

例:

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


  • ダウン投票者、細心の注意を払う? - Abdo

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

しかし、引数を渡す際にタスク名(デフォルトまたはビルド)を指定しないようにする方法は見つかりませんでした。誰かが方法を知っていれば聞いてみたいです。


2

上記の方法の大部分は私にはうまくいきませんでした、おそらくそれらは新しいバージョンでは推奨されていません。 最新のガイドはここにあります: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


2

引数の位置が何のためのものであるか覚えておくことに煩わされないなら、あなたはルビー引数ハッシュのような何かをしたいです。 1つの引数を使用して文字列を渡し、その文字列をオプションハッシュに正規表現することができます。

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


  • あなたのコードはいくつかの適切に配置された空行を必要とします。あなたがそのテキストの壁をどのように読んだのか私は知らない。 - Joshua Pinter

-5

パラメータを渡している間、それはより良い選択です入力ファイルです、これはあなたが必要とする変数名を含むそこからあなたが必要とするデータ構造と変数を読むことができます。 ファイルを読むためには、以下の構造を持つことができます。

  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 


  • RakeタスクにJSON命令ファイルが必要な場合は、おそらく、Rakeタスクであまりにも多くのことをしているでしょう。 - ZiggyTheHamster
  • これは方法非常に単純なことを過度に複雑にしている。 - jeffdill2

リンクされた質問


関連する質問

最近の質問