How to pass arguments into a Rake task with environment in Rails? [duplicate]
I am able to pass in arguments as follows:
desc "Testing args"
task: :hello, :user, :message do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{args[:user]}. #{:message}"
end
I am also able to load the current environment for a Rails application
desc "Testing environment"
task: :hello => :environment do
puts "Hello #{User.first.name}."
end
What I would like to do is be able to have variables and environment
desc "Testing environment and variables"
task: :hello => :environment, :message do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{User.first.name}. #{:message}"
end
But that is not a valid task call. Does anyone know how I can achieve this?
Just to follow up on this old topic; here's what I think a current Rakefile (since a long ago) should do there. It's an upgraded and bugfixed version of the current winning answer (hgimenez):
desc "Testing environment and variables"
task :hello, [:message] => :environment do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{User.first.name}. #{args.message}" # Q&A above had a typo here : #{:message}
end
This is how you invoke it (http://guides.rubyonrails.org/v4.2/command_line.html#rake):
rake "hello[World]"
For multiple arguments, just add their keywords in the array of the task declaration (task :hello, [:a,:b,:c]...
), and pass them comma separated:
rake "hello[Earth,Mars,Sun,Pluto]"
Note: the number of arguments is not checked, so the odd planet is left out:)
TLDR;
task :t, [args] => [deps]
Original Answer
When you pass in arguments to rake tasks, you can require the environment using the :needs option. For example:
desc "Testing environment and variables"
task :hello, :message, :needs => :environment do |t, args|
args.with_defaults(:message => "Thanks for logging on")
puts "Hello #{User.first.name}. #{args.message}"
end
Updated per @Peiniau's comment below
As for Rails > 3.1
task :t, arg, :needs => [deps] # deprecated
Please use
task :t, [args] => [deps]
Just for completeness, here the example from the docs mentioned above:
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
Notes:
- You may omit the
#with_defaults
call, obviously. - You have to use an
Array
for your arguments, even if there is only one. - The prerequisites do not need to be an
Array
. -
args
is an instance ofRake::TaskArguments
. -
t
is an instance ofRake::Task
.
An alternate way to go about this: use OS environment variables. Benefits of this approach:
- All dependent rake tasks get the options.
- The syntax is a lot simpler, not depending on the rake DSL which is hard to figure out and changes over time.
I have a rake task which requires three command-line options. Here's how I invoke it:
$ rake eaternet:import country=us region=or agency=multco
That's very clean, simple, and just bash syntax, which I like. Here's my rake task. Also very clean and no magic:
task import: [:environment] do
agency = agency_to_import
puts "Importing data for #{agency}..."
agency.import_businesses
end
def agency_to_import
country_code = ENV['country'] or raise "No country specified"
region_slug = ENV['region'] or raise "No region specified"
agency_slug = ENV['agency'] or raise "No agency specified"
Agency.from_slugs(country_code, region_slug, agency_slug)
end
This particular example doesn't show the use of dependencies. But if the :import
task did depend on others, they'd also have access to these options. But using the normal rake options method, they wouldn't.