31

I have seen examples where a task has parameters and a dependency task like:

task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
  args.with_defaults(:first_name => "John", :last_name => "Dough")
  puts "First name is #{args.first_name}"
  puts "Last name is #{args.last_name}"
end

How would you pass parameters to the name task if it was a task dependency like:

task :sendLetter => :name
  #do something
end
Nat Ritmeyer
  • 5,634
  • 8
  • 45
  • 58
dr.
  • 1,429
  • 12
  • 18

2 Answers2

33

Args are passed down through the call stack. You just need to make sure your top-level task captures all the arguments all of the dependencies require. In your case you'll want to put first_name and last_name on the send_letter task.

Here is an example that shows named arguments defined elsewhere flowing into the dependency (even if they aren't defined in the dependency), but the argument that doesn't match the name of the top-level task argument is nil.

desc 'Bar'
task :bar, :nom do |task, args|
  puts "BAR NOM: #{args[:nom]}"
  puts "BAR NAME: #{args[:name]}"
end

desc 'Foo'
task :foo, [:name] => :bar do |task, args|
  puts "FOO NAME: #{args[:name]}"
end

Running rake foo[baz] yields

BAR NOM: 
BAR NAME: baz
FOO NAME: baz

It is interesting to note that using args.with_defaults(nom: 'Jaques') in the foo task has no effect on the dependent task -- nom is still nil.

Rake version: rake, version 10.0.3

Ruby version: ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]

RonU
  • 5,525
  • 3
  • 16
  • 13
xtoddx
  • 511
  • 5
  • 4
  • 1
    Thank you, great help. But god I hope metasyntactic variables will die and good creative examples will come back. – William Entriken Mar 16 '17 at 15:43
  • What are metasyntactic variables, or rather, what of the above are you referring to? – Sixtyfive May 07 '19 at 14:29
  • I can see that defaults would not be passed because the dependencies would run before the `with_defaults` call. However, is there a good way to make this happen, other than extracting a constant for each default and manually ensuring that the `with_defaults` call is present in all dependent tasks that use the argument (or helper function call for all defaults)? – Sam Brightman Dec 14 '22 at 08:48
  • `with_defaults` doesn't change `args`, `with_defaults!` does. But yeah, it's executed after the prerequisites. – x-yuri Jan 20 '23 at 06:31
9

The closest you're probably going to get is either

task :sendLetter do
  task(:name).invoke("first", "last")
end

or

task :sendLetter do
  task(:name).execute(["first", "last"])
end

You can do something like

task :sendLetter => task(:name).invoke("first", "last")

but that will invoke name regardless of whether you ask for sendLetter or not.

Task#invoke only calls the task if it hasn't been called and calls any uncalled prereqs first. Task#execute always calls the task but does not call any prereqs. Note that the parameters don't affect the call-once nature of Task#invoke: if you invoke a parameterized task twice, it will only get run once, whether or not the parameters are different.

smparkes
  • 13,807
  • 4
  • 36
  • 61