How to pass array parameters to rake tasks using comma?

4,464 views
Skip to first unread message

Vikram Kumar

unread,
Mar 2, 2009, 11:06:15 AM3/2/09
to boston-r...@googlegroups.com
I want to run a rake task that can take in a specific AR id or an array of them.

It's simple using the old structure.

task :task1 => :environment => do 
  ids = ENV['IDS'].split(',')
  p ids
end

Using the above, you can do
rake task1 IDS=1,2,3
or
rake task1 IDS=1

However, if we pass the parameters

task :task2, [:batch_ids] => :environment => do |t, args|
  ids = args.batch_ids.split(',')
  p ids
end

you can never use "commas" as delimiters.  Only the first part (before the comma) works. 

rake task2[1,2,3]
or
rake task2[1]   

both default to just  ids=[1]


There is no way to make this work with comma as delimiter as rake treats ',' as args delimiter and discards those that have not been declared in the task definition as it converts parameters to openstruct.

I can make this work by using some other character for delimiter (currently ;).

Any clues?



Daniel Choi

unread,
Mar 2, 2009, 11:31:49 AM3/2/09
to Boston Ruby Group

There's no way to do this because of how the TaskArguments class in
rake (defined in lib/rake.rb in the rake gem) is instantiated. But you
could patch the #initialize method of this class to allow the globbing
behavior you want. Or you can keep using the first ENV['IDS'].split
approach to achieve the same result.

Here's the relevant code from class TaskArgument:

class TaskArguments
include Enumerable

attr_reader :names

# Create a TaskArgument object with a list of named arguments
# (given by :names) and a set of associated values (given by
# :values). :parent is the parent argument object.
def initialize(names, values, parent=nil)
@names = names
@parent = parent
@hash = {}
names.each_with_index { |name, i|
@hash[name.to_sym] = values[i] unless values[i].nil?
}
end

Daniel Choi

unread,
Mar 2, 2009, 5:20:26 PM3/2/09
to Boston Ruby Group

I tried writing up the patch I suggested:

require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

require 'tasks/rails'

module Rake
class TaskArguments
include Enumerable

attr_reader :names

# Create a TaskArgument object with a list of named arguments
# (given by :names) and a set of associated values (given by
# :values). :parent is the parent argument object.
def initialize(names, values, parent=nil)
@names = names
@parent = parent
@hash = {}
names.each_with_index { |name, i|

# if the variable name ends in _glob, glob all the rest of the
values
# into an array and assign it to the value.
puts name
if name.to_s =~ /_glob$/
@hash[name.to_sym] = values[i..-1]
else
@hash[name.to_sym] = values[i] unless values[i].nil?
end
}
end
end
end

task :task1, [:batch_ids] do |t, args|
puts t
puts args.inspect
end

task :task2, [:batch_ids_glob] do |t, args|
puts t
puts args.inspect
end



Output:
rake task1[1,2,3]
=>
task1
{:batch_ids=>"1"}


rake task2[1,2,3]
=>
task2
{:batch_ids_glob=>["1", "2", "3"]}

Vikram Kumar

unread,
Mar 4, 2009, 5:50:02 AM3/4/09
to boston-r...@googlegroups.com
Thank you. Trying it out...
Reply all
Reply to author
Forward
0 new messages