Rake Execute With Multiple Arguments - ruby-on-rails

I'm calling a rake task within a task and I'm running into a roadblock when it comes to calling execute
response = Rake::Task["stuff:sample"].execute[:match => "HELLO"]
or
response = Rake::Task["stuff:sample"].execute[:match => "HELLO",:freq=>'100']
Calling task
task :sample, [:match,:freq] => :environment do |t, args|
The error I get back is 'can't convert Hash into Integer'
Any ideas?

I think the problem is in code you're not posting. Works fine for me:
james#James-Moores-iMac:/tmp$ head r.rb call.rb
==> r.rb <==
task :sample, [:match,:freq] do |t, args|
puts "hello world"
puts args[:match]
end
==> call.rb <==
require 'rubygems'
require 'rake'
load 'r.rb'
Rake::Task["sample"].execute :match => "HELLO"
james#James-Moores-iMac:/tmp$ ruby call.rb
hello world
HELLO
james#James-Moores-iMac:/tmp$

The square brackets in your execute syntax confuse me. Is that a special rake syntax (that you may be using incorrectly) or do you mean to send an array with one element (a hash)?
Isn't it the same as this?
response = Rake::Task["sample"].execute([:match => "HELLO",:freq=>'100'])
Beyond that, Task#execute expects Rake:TaskArguments.
class TaskArguments
...
# 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)
You could use:
stuff_args = {:match => "HELLO", :freq => '100' }
Rake::Task["stuff:sample"].execute(Rake::TaskArguments.new(stuff_args.keys, stuff_args.values))
You could also use Task#invoke, which will receive basic args. Make sure you Task#reenable if you invoke it multiple times.

This post is pretty old but I found the first answer is wrong by passing a hash inside an array. We can send arguments by passing them as a hash as following
response = Rake::Task["sample"].execute(match: "HELLO", freq: 100)
Inside the rake task, we can access them in args as args[:match] and args[:freq].to_i

Related

Why is `:environment` passed to a rake task as an array?

I am looking at the first line of following rake task:
task :generate_course_group_progress_report => [:environment] do
Why is [:environment] passed as the value of the hash as an array instead of :environment? what does this do? This doesn't seem to break the task.
Is there a scenario where I would pass multiple variables to the hash, i.e [:environment, :something_else]?
No, you can use it also as a symbol.
task test_task: :environment do
# some code
end

Don't change string value on insert

I have a Model user with the following method:
def number_with_hyphen
number&.insert(8, "-")
end
When I run it several times in my tests I get the following output:
users(:default).number_with_hyphen
"340909-1234"
(byebug) users(:default).number_with_hyphen
"340909--1234"
(byebug) users(:default).number_with_hyphen
"340909---1234"
(byebug) users(:default).number_with_hyphen
"340909----1234"
It changes the number ?Here are the docs https://apidock.com/ruby/v1_9_3_392/String/insert
When I restructure my method to:
def number_with_hyphen
"#{number}".insert(8, "-") if number
end
If works like expected. The output stays the same!
How would you structure the code, how would you perform the insert?
which method should I use instead. Thanks
If you're using the insert method, which in the documentation explicitly states "modifies str", then you will need to avoid doing this twice, rendering it idempotent, or use another method that doesn't mangle data.
One way is a simple regular expression to extract the components you're interested in, ignoring any dash already present:
def number_with_hyphen
if (m = number.match(/\A(\d{8})\-?(\d+)\z/))
[ m[1], m[2] ].join('-')
else
number
end
end
That ends up being really safe. If modified to accept an argument, you can test this:
number = '123456781234'
number_with_hyphen(number)
# => "12345678-1234"
number
# => "123456781234"
number_with_hyphen(number_with_hyphen(number))
# => "12345678-1234"
number_with_hyphen('1234')
# => "1234"
Calling it twice doesn't mangle anything, and any non-conforming data is sent through as-is.
Do a clone of the string:
"#{number}".clone.insert(8, '-')

Why is this create statement giving the error "ArgumentError: wrong number of arguments (1 for 2)"?

Having trouble with this seemingly simple task of importing a CSV file via a Rake task, and storing in multiple tables.
My rake task:
desc "Imports the COGCC CSV file into wikifrac database"
task :import_cogcc => :environment do
require 'csv'
CSV.foreach('public/partial.csv', :headers => true) do |row|
# create records in independent tables
# create the Company object
this_company_name = row['name'].strip!
this_operator_num = row['operator_num']
if !(Companies.exists?(:company_name => this_company_name))
Companies.create(:company_name => this_company_name, :operator_num => this_operator_num)
end
thecompany = Companies.find(:first, :conditions => ["this_company_name = ?", this_company_name])
company_id = thecompany.id
...
My Companies model:
class Companies < ActiveRecord::Base
has_many :facilities, dependent: :destroy
attr_accessor :company_name, :operator_num
def initialize(company_name, operator_num)
#operator_num = operator_num
#company_name = company_name
end
end
But when I run rake import_partial, I get this error:
rake aborted! ArgumentError: wrong number of arguments (1 for 2)
wfrails/app/models/companies.rb:5:in
initialize'
wfrails/lib/tasks/import_partial.rake:47:in
block (2 levels) in '
wfrails/lib/tasks/import_partial.rake:26:in
`block in ' Tasks: TOP => import_cogcc
Can anyone tell me what's wrong with this? Have been going around and around with this; many similar examples in SO, but cannot quite solve my error....
The error is because you are calling create with a hash in your rake task. The hash is counted as 1 object (the syntax you use has implicit curly braces around it, so you are really passing in {:company_name => this_company_name, :operator_num => this_operator_num}), whereas you have overridden the initialize method to take 2 arguments separately. Hence, it complaining it only find 1 parameter where it expects 2.
Easy way
Since you are using activerecord, I would do what BroiSatse says and just remove your initialize overridden method. This will allow the hash to work correctly, and will automatically set the attributes you send in.
Special case
If for some reason, you want to set those two variables as part of the initialization, I would make sure you call super so that the rest of the object is set correctly.
ruby
def initialize(params={})
super
self.operator_num = params[:operator_num]
self.company_name = params[:company_name]
end
But I only do this if I need these attributes set before I run any of my callbacks.

Passing a parameter or two to a Rake task

I have a rake task that I want to pass parameters to. For example, I want to issue a command like
<prompt> rake db:do_something 1
and inside the rake task:
...
cust = Customer.find( the_id_passed_in )
# do something with this customer record, etc...
...
Pretty straightforward, right?
The way rake commands accept and define arguments is, well, not pretty.
Call your task this way:
<prompt> rake db:do_something[1,2]
I've added a second parameter to show that you'll need the comma, but omit any spaces.
And define it like this:
task :do_something, :arg1, :arg2 do |t, args|
args.with_defaults(:arg1 => "default_arg1_value", :arg2 => "default_arg2_value")
# args[:arg1] and args[:arg2] contain the arg values, subject to the defaults
end
While passing parameters, it is better option is an input file, can this be a excel a json or whatever you need and from there read the data structure and variables you need from that including the variable name as is the need.
To read a file can have the following structure.
namespace :name_sapace_task do
desc "Description task...."
task :name_task => :environment do
data = ActiveSupport::JSON.decode(File.read(Rails.root+"public/file.json")) if defined?(data)
# and work whit yoour data, example is data["user_id"]
end
end
Example json
{
"name_task": "I'm a task",
"user_id": 389,
"users_assigned": [389,672,524],
"task_id": 3
}
Execution
rake :name_task

How to pass more than one argument to a worker at backgroundrb

I'm trying to pass a list of arguments to a backgroundrb
in documentation it says: MiddleMan.worker(:billing_worker).async_charge_customer(:arg => current_customer.id)
but it only works for just one argument, I tried these but none worked for me
args => [1,2,3]
args => {:t=>"t", :r=> "r"}
any ideas how to solve this??
What you are trying seems reasonable to me. I took a look at rails_worker_proxy.rb (from the github source code). From a code read, the async_* methods accept both :arg and :args:
arg,job_key,host_info,scheduled_at,priority = arguments && arguments.values_at(:arg,:job_key,:host,:scheduled_at, :priority)
# allow both arg and args
arg ||= arguments && arguments[:args]
# ...
if worker_method =~ /^async_(\w+)/
method_name = $1
worker_options = compact(:worker => worker_name,:worker_key => worker_key,
:worker_method => method_name,:job_key => job_key, :arg => arg)
run_method(host_info,:ask_work,worker_options)
Can you share a code snippet? Have you added any debugging statements in your code and/or in the backgroundrb code itself? (I usually add a few puts statements and inspect things when things go wrong.)
Lastly, have you considered using delayed_job? It has more traction nowadays in the Rails community.
Actually, the second method you've tried (args => {:t=>"t", :r=> "r"}) should work.
In your worker:
def charge_customer(arg)
customer_id = arg[:customer_id]
customer_name = arg[:customer_name]
#do whatever you need to do with these arguments...
end
And then, you can call the worker like this:
MiddleMan.worker(:billing_worker).async_charge_customer(:arg => { :customer_id => current_customer.id, :customer_name => current_customer.name })
Basically, what you're doing here is pass a single Hash as the one argument the worker accepts. But since a Hash can contain multiple key-value pairs, you can access all of these individually inside your worker.

Resources