Unable to change passed arguments to rake tasks - ruby-on-rails

When I specify the value for argument, it is a string. So I tried to turn it into an integer, but this is not working.
Code is like this:
task :fetch_video, [:fetch_number] => :environment do |t, args|
args.with_defaults(:fetch_number => 4)
args.fetch_number = args.fetch_number.to_i
puts args.fetch_number.class
#run rake fetch_video[10],
#returns: String
end
What mistake did I make?

You're trying to write the args variable, I don't think you can do that. Try this:
task :fetch_video, [:fetch_number] => :environment do |t, args|
args.with_defaults(:fetch_number => 4)
local_fetch_number = args.fetch_number.to_i
puts local_fetch_number.class
end

Related

I don't understand how to add arguments to a rake task. (Excerpt from the documentation)

I'm trying to create a custom rake task that takes in two arguments and uses them in my code.
I'm looking at the rails documentation and I see this excerpt for running a rails task with an argument:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
The rake task can then be invoked like this:
bin/rake "task_name[value 1]"
However, this is way too vague for me. The rails documentation fails to give a concrete example of a rake task with an argument.
For example, I'm looking at this code and I'm thinking what does bin/rake "task_name[value 1]" do? What is [:pre1, :pre2]?
Additionally, I've found some other fantastic links that do things a little bit differently. Here are the links.
Thoughtbot version
In the thoughtbot version that have this example
task :send, [:username] => [:environment] do |t, args|
Tweet.send(args[:username])
end
What is the [:username => [:environment]? its different than the official rails docs.
Here is another:
4 ways to write rake tasks with arguments
I've also looked at the officail optparser documentation and that too has a different way of making it work.
All I want is for this example code that I have to work on my .rake file:
require 'optparse'
task :add do
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: rake add"
opts.on("-o", "--one ARGV", Integer) { |one| options[:one] = one }
opts.on("-t", "--two ARGV", Integer) { |two| options[:two] = two }
end.parse!
puts options[:one].to_i + options[:two].to_i
end
The code fails because of invalid option: -o. I just want to make this work so I can move on. Does anyone have any thoughts?
Here is one of my rake tasks with arguments:
namespace :admin do
task :create_user, [:user_email, :user_password, :is_superadmin] => :environment do |t, args|
email = args[:email]
password = args[:password]
is_superadmin = args[:is_superadmin]
... lots of fun code ...
end
end
and I invoke this task like this:
rake admin:create_user['admin#example.com','password',true]
EDIT
To pass flags in you can do something like this:
task :test_task do |t, args|
options = {a: nil, b: nil}
OptionParser.new do |opts|
opts.banner = "Usage: admin:test_task [options]"
opts.on("--a", "-A", "Adds a") do |a|
options[:a] = true
end
opts.on("--b", "-B", "Adds b") do |b|
options[:b] = true
end
end.parse!
puts options.inspect
end
And examples of invoking it:
rake admin:test_task -A -B
rake admin:test_task -A
rake admin:test_task -B

How to pass an option to a Rake task?

I would to know if it was possible to pass an option from the commande line to the task without having the Rakefile taking option for itself.
Here is my task:
task :task do
args = ARGV.drop(1)
system("ruby test/batch_of_test.rb #{args.join(' ')}")
args.each { |arg| task arg.to_sym do ; end }
end
Here is the command I want to be functional:
rake task --name test_first_one
The result I want is the same as this:
ruby test/batch_of_test.rb --name test_first_one
For this code, I get this error:
invalid option: --name
How can --name (or another option) can be passed to my task ?
As far as I know you cannot add flags to Rake tasks. I think the closest syntax available is using ENV variables.
rake task NAME=test_first_one
Then in your task:
name = ENV['NAME']
like this:
task :task, [args] => :environment do |t, args|
system("ruby test/batch_of_test.rb #{args.join(' ')}")
args.each { |arg| task arg.to_sym do ; end }
end
and you call it like this.
rake task[args]
UPDATE
task :task, [:options] => :environment do |t, args|
arg = args[:options].pop
options = args[:options]
end

How do I pass an argument from a child task to a parent task in Rake

I tried invoke, but I don't think it's going to help. Here is a short demo of what I am try to achieve.
task :first_task => :dep do
puts "something else"
end
task :dep do
puts "something"
end
If I run
rake first_task
from the command-line, the dependency gets satisfied and then the first_task gets executed.
something
something else
But what if I have a value, say dir = "testdir" in :dep that I want to pass as an argument to :first_task? Hope that makes sense.
I thought google would come up with something, but nope. Thanks a lot :)
Not sure if you can set or pass a parameter, but you can use instance variables:
task :first_task => :dep do
puts "something else"
puts #dir
end
task :dep do
puts "something"
#dir = "Foo"
end
Or just local variables:
dir = "default_dir"
task :first_task => :dep do
puts "something else"
puts dir
end
task :dep do
puts "something"
dir = "Foo"
end
For some kinds of task, it may make more sense to set environment variables:
task :first_task => :dep do
puts "something else"
puts ENV['dir']
end
task :dep do
puts "something"
ENV['dir'] = "Foo"
end
It doesn't fit completely to your question, but is may show another approach for parameters with rake and forwarding them to child tasks. Rake tasks may get parameters.
An example:
task :first_task, [:par1, :par2] do |t, args|
puts "#{t}: #{args.inspect}"
end
You can call this task with rake first_task[1,2] The result will be:
first_task: {:par1=>1, :par2=>2}
This parameters are forwarded to child tasks, if they share the same key. Example:
task :first_task, [:par1, :par2] => :second_task do |t, args|
puts "#{t}: #{args.inspect}"
end
task :second_task, :par2 do |t, args|
puts "#{t}: #{args.inspect}"
end
The result:
second_task: {:par2=>2}
first_task: {:par1=>1, :par2=>2}

How do I pass arguments to my rake task in ruby

I've seen similar questions here, couldn't figure out the answer I'm just starting with ror development. I've got a rake task :
namespace:generate do
desc "Export to txt"
task :txt => :environment do |t, args|
puts "testing #{args}"
end
end
When I do this from command line:
rake generate:txt
I get testing {}
When I try to inject value as an argument like this :
rake generate:txt[testvalue] or
rake generate:txt testvalue
First one does nothing same output testing {} second one I get an error. So in which way do I invoke command so I populate args with some value(s)?
IIRC, you have to declare parameters explicitly.
task :environment do
puts "setting up env"
end
namespace :generate do
desc "Export to txt"
task :txt, [:filename] => :environment do |t, args|
puts "testing #{args}"
end
end
Then
% rake generate:txt['foo']
setting up env
testing {:filename=>"foo"}
namespace:generate do
desc "Export to txt"
task :txt, [:arg1] => :environment do |t, args|
puts "testing #{args[:arg1]}"
end
end
rake generate:csv arg1="value"

How to pass arguments into a Rake task with environment in Rails? [duplicate]

This question already has answers here:
How to pass command line arguments to a rake task
(20 answers)
Closed 5 years ago.
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 of Rake::TaskArguments.
t is an instance of Rake::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.
While these solutions work, in my opinion this is overly complicated.
Also, if you do it this way in zsh, you'll get errors if the brackets in your array aren't escaped with '\'.
I recommend using the ARGV array, which works fine, is much simpler, and is less prone to error. E.g:
namespace :my_example do
desc "Something"
task :my_task => :environment do
puts ARGV.inspect
end
end
then
rake my_example:my_task 1 2 3
#=> ["my_example:my_task", "1", "2", "3"]
The only thing you need to keep in mind is that ARGV[0] is the process name, so use only ARGV[1..-1].
I realize that strictly speaking this does not answer the question, as it does not make use of :environment as part of the solution. But OP did not state why he included that stipulation so it might still apply to his use case.

Resources