rake task with multiple parameters - I got stuck - ruby-on-rails

The rake task itself:
desc "This task creates a new user"
task :create_user, [:email, :password] => :environment do |t, args|
trole = Role.find_by_name('translator')
User.create(
:email => args.email,
:password => args.password,
:password_confirmation => args.password,
:role_id => trole.id)
end
The call:
rake create_user[user#host.com,password]
The output:
rake aborted!
Don't know how to build task 'create_user'
I really got stuck. All the advices I've found, even here, on StackOverflow, either don't cover the situation with two parameters, or are outdated/not working. Please help!

The syntax you've written should work fine in bash, so I'm guessing you're using zsh?
If so, it can't parse the [] correctly and these need to be escaped.
Try using:
rake create_user\[user#host.com,password\]
instead.

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

I received an error Importing CSV file to ruby on rails

I used the following code to try to import a csv file into rails.
(it was provided by Erik on Rails blog)
#lib/tasks/import.rake
desc "Imports a CSV file into an ActiveRecord table"
task :csv_model_import, :filename, :model, :needs => :environment do |task,args|
lines = File.new(args[:filename]).readlines
header = lines.shift.strip
keys = header.split(',')
lines.each do |line|
values = line.strip.split(',')
attributes = Hash[keys.zip values]
Module.const_get(args[:model]).create(attributes)
end
end
then I ran the rake task rake csv_model_import[excelfilename.csv, name]. I have tried many approaches but just cant seem to get the csv file into my db/active record.
Error I received was :
"NoMethodError: undefined method `map' for :needs:Symbol"
I have no clue how to solve it. Please help me out guys, thanks.
I think you need brackets around your rake task arguments.
Try changing this:
task :csv_model_import, :filename, :model, :needs => :environment do |task,args|
to this:
task :csv_model_import, [:filename, :model, :needs] => :environment do |task,args|

Pass Hash as Parameter to Rake Task

I've got a rake task
task :post_hit, [:host, :title, :description, :model, :num_assignments, :reward, :lifetime, :qualifications, :p, :opts] => :environment do |t, args|
:p needs to be a hash, but if I try:
rake turkee:post_hit["http://www.staging.collegesportsbluebook.com","LS Info","Fill In Player First Name","MechanicalTurk",100,0.01,2,{},{id: 5},{}]
It errors out saying that id: could not be parsed (the space seemed to do something).
If I tried:
rake turkee:post_hit["http://www.staging.collegesportsbluebook.com","LS Info","Fill In Player First Name","MechanicalTurk",100,0.01,2,{},{"id: 5"},{}]
the who string "id: 5" was being interpreted as a single string.
Are we not allowed to pass hashes to rake tasks?
I use querystring-like parameters and parse them with Rack::Utils.parse_nested_query
Here's how I do it
require 'rack/utils' # needed for Rack::Utils.parse_nested_query
namespace :foo do
task :bar, [ :args_expr ] => :environment do |t, args|
args.with_defaults(:args_expr => "name=abdo&fruits[]=bananas&fruits[]=dates")
options = Rack::Utils.parse_nested_query(args[:args_expr])
puts options
end
end
And I call it like this: (notice how arrays and hashes are passed)
bundle exec rake "foo:bar[name=abdo&fruits[]=apples&fruits[]=oranges&hash[foo]=bar&hash[cool]=notmuch]"
Output:
{"name"=>"abdo", "fruits"=>["apples", "oranges"], "hash"=>{"foo"=>"bar", "cool"=>"notmuch"}}
When you issue a rake task via the terminal, you are in the UNIX or Bash environment, so you need to obey the rules of that language, which as far as I can tell doesn't include hashes. I could be wrong though.
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html#toc5
This doesn't mean that whoever wrote the rake task didn't do something clever to parse a string into a hash. If I were you and trying to figure it out I would have a look at the source code and see how that rake task parses it's variables.
PS. If it's a gem you are using and you are using bundler as well, you can issue bundle open gem_name to open up the source, rake tasks generally end in a .rake...
Try declaring your :p variable in task as a hash maybe? :p => {}
task :post_hit, [:host, :title, :description, :model, :num_assignments, :reward, :lifetime, :qualifications, :p => {}, :opts

Using factory_girl within a rake task - getting uninitialized constant

I'm trying to use Factory Girl in a rake task like this:
require 'factory_girl'
require File.expand_path("spec/factories.rb")
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
Factory(:user, :email => "pending#acme.com")
Factory(:approved_user, :email => "user#acme.com")
end
end
However when I run rake users:create_sample_users I get the error uninitialized constant Entry (Entry is the name of one of my app's classes).
Can anyone tell me how to get Factory girl to see my classes? It's working fine in my tests, just failing in my rake tasks.
I'm guessing that Rails hasn't loaded your models at the point you are requiring the factories. Try this:
require 'factory_girl'
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
require File.expand_path("spec/factories.rb")
Factory(:user, :email => "pending#acme.com")
Factory(:approved_user, :email => "user#acme.com")
end
end
For factory_bot which has replaced factory_girl use:
require 'factory_bot'
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
include FactoryBot::Syntax::Methods
create(:user, :email => "pending#acme.com")
end
end
#dmcnally's answer didn't work for me, as I was getting odd errors of constants not found. Instead, I resolved it by shelling out to rails runner:
sh "rails runner 'FactoryGirl.create :user'"

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