Ruby console - can't initialize a class with variables - ruby-on-rails

I am using Ruby console. I start it by using Rails console and then do require 'path to my file' which works fine.
The file looks like this:
module App
module Tools
module Pollers
class Kpi
attr_reader :start_time,:stop_time
def initialize(start_time,stop_time)
#start_time = start_time
#stop_time = stop_time
end
def create_social_audiences
....
So what I do is declare the stop and start time like this in the console
var end_date = new Date(2012, 7, 1);
var start = new Date(2012, 5, 1);
and then I try to call .new on this file and get this error
>> kpi = App::Tools::Pollers::Kpi.new
ArgumentError: wrong number of arguments (0 for 2)
from (irb):7:in `initialize'
from (irb):7:in `new'
from (irb):7
>>
but the weird part is that if I do this command which attempts to pass the variables it works:
>> kpi = App::Tools::Pollers::Kpi.new(start , end_date)
=> #<App::Tools::Pollers::Kpi:0x11489e198 #start_time=nil, #stop_time=nil>
but then when I try to do set the varialbes to anything other than nil I get errors that initialize is a private method:
?> kpi.initialize(start, end_date)
NoMethodError: private method `initialize' called for #<App::Tools::Pollers::Kpi:0x11489e198>
from (irb):15
Any thoughts on what might be happening wrong here?
Thanks!!

You should not call the class initializer after the class has been instantiated (and you cannot from outside of the class itself, given that it has private visibility).
The following does not work because you have an initializer with two parameters, therefore you also must pass those:
kpi = App::Tools::Pollers::Kpi.new
This works because the initializer is called when the class is being constructed (the initialize method is always invoked when you create a new instance using new):
kpi = App::Tools::Pollers::Kpi.new(start , end_date)
Finally, the following does not work (no matter what values start/end_date hold) because, as I explained earlier, the initializer of a class is private in ruby:
kpi.initialize(start, end_date) # Breaks!
If you want to modify these variables after constructing the class, create a method for that:
def initialize(start, end)
set_time(start_end)
end
def set_time(start, end)
#start_time = start
#end_time = end
end

Related

wrong number of arguments (given 4, expected 0..1) after upgrading to Rails 6

I just upgraded from Rails 5.2 to Rails 6 and I'm facing an issue in one class.
class Calculator < ApplicationRecord
def initialize(obj, user_id, calc_type, will_id = nil )
#inheritors = obj
super_obj = obj.clone.merge!(user_id: user_id, type: calc_type, will_id: will_id)
super(super_obj)
#shares = {}
#remains = RationalWithArgumentStore(0)
#stop_residual_shares = false
#special_case_apply = false
#rules = {}
#authorities = {}
end
end
and I'm creating new instance of the class like the following
calc = Calculator.new(obj, user_id, calc_type, nil)
It through an error saying:
wrong number of arguments (given 4, expected 0..1)
I spent two days searching and trying to fix the issue without any luck.
Your help is highly appreciated
This is happening because you are redefining initialize for a class that inherits from ApplicationRecord. It throws an error here. If you were to do the following it would work.
class Calculator
def initialize(obj, user_id, calc_type, will_id = nil)
#obj = obj
#user_id = user_id
#calc_type = calc_type
#will_id = will_id
end
end
Note that redefining initialize in this way is not recommended (see docs here), so if you can I would look into callbacks and see if you can accomplish your goal with that.
Hope that helps.
(Rails 6.x) One of my models had include Rails.application.routes.url_helpers.
If you have the same problem, remove it and manage your url methods by calling it directly as:
def my_link_function
# ... my code
my_link = Rails.application.routes.url_helpers.url_for([my_params]))
# ... other code
end

How to stub a method that sets an object attribute in a Rails test?

I'm building a Rails spec test that has a Struct called temp_coverage, like this:
temp_coverage = Struct.new(:paydays) do
def calculate_costs
50
end
end
And in my spec, I call a method using the temp_coverage, but I'm getting an error since the code I am testing is doing the following:
temp_coverage.req_subscriber_election_amount = subscriber_election_amount
And I am getting an error:
NoMethodError: undefined method `req_subscriber_election_amount=' for < struct paydays=12 >
How can I stub out the setting of an attribute on a struct in my spec?
Is something like this you're looking for?
temp_coverage = double('temp_coverage', paydays: nil)
allow(temp_coverage).to receive(:calculate_costs).and_return(50)
allow(temp_coverage).to receive(:req_subscriber_election_amount=) do |argument|
temp_coverage.instance_variable_set(:#req_subscriber_election_amount, argument)
end
# Example:
temp_coverage.req_subscriber_election_amount = 123
puts temp_coverage.instance_variable_get(:#req_subscriber_election_amount)
# => 123
puts temp_coverage.paydays
# => nil
puts temp_coverage.calculate_costs
# => 50
I found a way to do this by using a named Struct. So once I named my Struct:
temp_coverage = Struct.new('CoverageClass', :paydays) do
def calculate_costs
50
end
end
I could then do the following:
Struct::CoverageClass.any_instance.stubs(:req_subscriber_election_amount).returns(25)

Argument Error : Wrong number of arguments

I am writing the following in rails console.
> class Hello
> def method
> d = Jobs.find_by_sql("select id, count(*) as TOTAL from table group by id having count>100")
> d.each do |m|
> puts m.account_id
> end
> end
> end
=> :method
> Hello.method
ArgumentError: wrong number of arguments (0 for 1)
I can't figure out what's wrong in this code. How can I solve this error.
your method name "method" is an existing method of the Object class, which is ultimately inherited by all classes in ruby.
You define an instance method with this name, which would be fine and would override the inherited instance method if it existed already. However, when you come to call it, you're calling it as a class method (because you're calling it on Hello, which is the class), so you're calling the existing "method" method, which is complaining about not getting any parameters.
Change your method to be called "foo" and then try to do Hello.foo. You'll get an "undefined method or variable" error because there's no foo class method.
Then do
hello = Hello.new
hello.foo
and it will work.
EDIT:
If you want it to actually be a class method, then you can do it via either of these ways:
class Hello
def self.method
d = Jobs.find_by_sql("select id, count(*) as TOTAL from table group by id having count>100")
d.each do |m|
puts m.account_id
end
end
end
end
or
class Hello
#class methods go in here
class << self
def method
d = Jobs.find_by_sql("select id, count(*) as TOTAL from table group by id having count>100")
d.each do |m|
puts m.account_id
end
end
end
end
end
As an aside, it's a convention, and generally a good idea, to use meaningful variable names. For example, if you have a variable which is a collection of Job objects, call it "jobs", not "d". Then anyone reading your code can easily remember what is held in that variable.
Using this principle, i would rewrite your code thus:
def output_job_account_ids
jobs = Jobs.find_by_sql("select id, count(*) as TOTAL from table group by id having count>100")
jobs.each do |job|
puts job.account_id
end
end
end
See how it's immediately much more obvious what is happening? I renamed the method name too: it's generally a good idea to have a method name describe what the method does.

Spree error when using decorator with the original code

Need a little help over here :-)
I'm trying to extend the Order class using a decorator, but I get an error back, even when I use the exactly same code from source. For example:
order_decorator.rb (the method is exactly like the source, I'm just using a decorator)
Spree::Order.class_eval do
def update_from_params(params, permitted_params, request_env = {})
success = false
#updating_params = params
run_callbacks :updating_from_params do
attributes = #updating_params[:order] ? #updating_params[:order].permit(permitted_params).delete_if { |k,v| v.nil? } : {}
# Set existing card after setting permitted parameters because
# rails would slice parameters containg ruby objects, apparently
existing_card_id = #updating_params[:order] ? #updating_params[:order][:existing_card] : nil
if existing_card_id.present?
credit_card = CreditCard.find existing_card_id
if credit_card.user_id != self.user_id || credit_card.user_id.blank?
raise Core::GatewayError.new Spree.t(:invalid_credit_card)
end
credit_card.verification_value = params[:cvc_confirm] if params[:cvc_confirm].present?
attributes[:payments_attributes].first[:source] = credit_card
attributes[:payments_attributes].first[:payment_method_id] = credit_card.payment_method_id
attributes[:payments_attributes].first.delete :source_attributes
end
if attributes[:payments_attributes]
attributes[:payments_attributes].first[:request_env] = request_env
end
success = self.update_attributes(attributes)
set_shipments_cost if self.shipments.any?
end
#updating_params = nil
success
end
end
When I run this code, spree never finds #updating_params[:order][:existing_card], even when I select an existing card. Because of that, I can never complete the transaction using a pre-existent card and bogus gateway(gives me empty blanks errors instead).
I tried to bind the method in order_decorator.rb using pry and noticed that the [:existing_card] is actuality at #updating_params' level and not at #updating_params[:order]'s level.
When I delete the decorator, the original code just works fine.
Could somebody explain to me what is wrong with my code?
Thanks,
The method you want to redefine is not really the method of the Order class. It is the method that are mixed by Checkout module within the Order class.
You can see it here: https://github.com/spree/spree/blob/master/core/app/models/spree/order/checkout.rb
Try to do what you want this way:
Create file app/models/spree/order/checkout.rb with code
Spree::Order::Checkout.class_eval do
def self.included(klass)
super
klass.class_eval do
def update_from_params(params, permitted_params, request_env = {})
...
...
...
end
end
end
end

How to pass Arguments and use those in (resque-status) Resque::JobWithStatus?

my resque worker class is:
require 'resque'
require 'resque/job_with_status'
class PatstatResqueWorker < Resque::JobWithStatus
#queue = :my_worker_q
def self.perform(query, label)
puts "query:"
puts options['query']
puts "label:"
puts options['label']
end
end
and my controller part, where I call this resque is...
class MyController < ApplicationController
def resque
job_id = PatstatResqueWorker.create(:query => #query, :label => "yes")
status = Resque::Plugins::Status::Hash.get(job_id)
end
end
and its not working :(
if i remove the parameter from resque function it says Wrong number of arguments (2 for 0) and if i add the parameter section back it says options not defined :(
Could you help?
The reason you're getting the "options not defined" error is that you haven't defined options in the method that uses it. Your self.perform method expects to receive two distinct arguments, query and label, but the code inside the method expects to have an options hash. You've got to choose one or the other.
Either do this:
def self.perform(query, label)
# use the parameters we've already defined
puts "query:"
puts query
puts "label:"
puts label
end
# call it like this
PatstatResqueWorker.create(#query, "yes")
Or else do this:
# change the method signature to match what you're doing
def self.perform(options)
puts "query:"
puts options['query']
puts "label:"
puts options['label']
end
# call it like this, with string keys
PatstatResqueWorker.create('query' => #query, 'label' => "yes")
Notice that with the hash version, I changed the call to use strings for the hash keys instead of symbols. You can use symbols if you want, but you'd have to change it in the body of the method as well (i.e. options[:query] instead of options['query']). You've just got to be consistent.

Resources