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

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

Related

why is ruby expecting wrong number of arguments

I have a rails app where I am setting up a method before_save activeRecord callback, like this:
class GroupEvent < ApplicationRecord
enum status: [ :published, :draft ]
before_save :calculate_and_set_dates
def calculate_and_set_dates
missing_properties = []
#check for available or set attributes
puts "sss" + self.startDate.to_s
if !self.startDate
missing_properties<<"startDate"
end
if !self.duration
missing_properties<<"duration"
end
if !self.endDate
missing_properties<<"endDate"
end
binding.pry
if missing_properties.length<=1
set_missing_property(missing_properties[0])
else
set_errors_for(missing_properties)
end
end
private
def set_missing_property(missing_property)
case missing_property
when "startDate"
self.startDate = self.endDate - self.duration
when "duration"
self.duration = self.endDate - self.startDate
when "endDate"
self.endDate= self.startDate +self.duration
end
end
end
Note: this note the complete class so don't worry about set_errors_for methods implimentation.
Now when, I create a groupEvent using GroupEvent.create(name:"hackaton",description:"hecking my life away",startDate: DateTime.now, duration:10). At point where set_missing_property(missing_properties[0]) is called ,I get an error for wrong number of arguments:
ArgumentError: wrong number of arguments (given 1, expected 0) from /Users/haroonAzhar/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.4/lib/active_record/attribute_methods/read.rb:15:in startDate'
As you can see that the method set_missing_property has 1 argument in definition, why is it expecting 0? What's even more confusing is that: when i pass no argument to the 'set_missing_property' method I get this error:
ArgumentError: wrong number of arguments (given 0, expected 1) from /Users/haroonAzhar/Desktop/develop/whitespectre/app/models/group_event.rb:29:in set_missing_property'
I don't know why it's looking at
/Users/haroonAzhar/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.4/lib/active_record/attribute_methods/read.rb:15:in startDate'
when I give one parameter/argument but i checked out the file it was suggesting and the part it is referring to looks like this:
module ClassMethods # :nodoc:
private
def define_method_attribute(name)
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
generated_attribute_methods, name
) do |temp_method_name, attr_name_expr|
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{temp_method_name}
name = #{attr_name_expr}
_read_attribute(name) { |n| missing_attribute(n, caller) }
end
RUBY
end
end
end
what is even look for at that place when the defined method is right in the class ? but the real question to which I need answer is why is it expecting wrong number of arguments and how do I fix it?
Thankyou in advance for your help, really appreciate it :D
Alright guys, I solved it(Maybe)
So at endDate case inside my set_missing_property, I changed it to:
when "endDate"
self.endDate = self.startDate + self.duration
I believe I was calling the self.startDate with a argument which doesnt expect any,so it was throwing that error.
Thanks for giving it a look to all the peeps that gave their time to this. really appreciate it.

Strange behavior for method default parameters initialization

When I am trying to initialize this it is working perfectly fine
class Abc
def initialize(parent_id, user = nil, permission)
end
end
Abc.new(1 ,2, "some_permission")
But when I am doing this
class Abc
def initialize(parent_id, user = nil, permission, g_data = nil)
end
end
Abc.new(1 ,2, "some_permission", 4)
I am getting syntax error syntax error, unexpected '=', expecting ')'
This is a strange behavior why it is not taking two arguments default as nil
According to ruby documentation the default values should be grouped.
The default value does not need to appear first, but arguments with
defaults must be grouped together.
So according to this rule your method arguments should be listed like following:
class Abc
def initialize(parent_id, user = nil,g_data = nil,permission)
end
# OR
def initialize(parent_id, permission,user = nil,g_data = nil)
end
end

Ruby on Rails -- NameError '#' not allowed as an instance variable name

I am fairly new to Ruby on Rails and have been stuck with this bug for quite sometime now. I am hoping that someone could give me some useful information to fix this bug. I have a feeling I am overlooking something trivial. Anyhow, I have included below my code that is drawing the Error (that is in the View) and also my code that is in my controller. While I have done my research before posting on here, I may have to put my instance variable in my controller -- however, I am unsure how that process goes and then how to call it from my View. I would appreciate any help! Thanks in advance :)
The error I get:
NameError in Search#indx
'#' is not allowed as an instance variable name
Here is my line of code that is drawing the error in my view (apps/views/search/index.html.erb):
<% #search = instance_variable_get("\##{params[:model].to_s.downcase.pluralize}")%>
Here is my code in my controller (apps/controllers/search_controller.rb):
class SearchController < ApplicationController
def index
#containers = Container.search(params[:q])
#cpus = Cpu.search(params[:q])
#disks = Disk.search(params[:q])
#firmwares = Firmware.search(params[:q])
#hardwares = Hardware.search(params[:q])
#hosts = Host.search(params[:q])
#interfaces = Interface.search(params[:q])
#lans = Lan.search(params[:q])
#licenses = License.search(params[:q])
#rams = Memory.search(params[:q])
#networks = Network.search(params[:q])
#products = Product.search(params[:q])
#roles = Role.search(params[:q])
#sites = Site.search(params[:q])
#vmpools = Vmpool.search(params[:q])
#trackings = Tracking.search(params[:q])
end
end
The problem is that params[:model] is nil, so you're essentially doing instance_variable_get("#").
Take a look at the Rails log and see if the params you think are being received are actually being received.
Edit: The below is not directly related to the problem you're having (the previous two sentences explain why you're having that problem), but rather a suggestion for improving the way your code is organized.
Doing instance_variable_get in a view is a pretty bad code smell. Really, doing instance_variable_get at all is a code smell. There's almost certainly a better way to do what you're trying to do. For example:
def index
query = search_params[:q]
#search_results = {
containers: Container.search(query),
cpus: Cpu.search(query),
disks: Disk.search(query),
# ...
}
model = search_params[:model].to_s.downcase.pluralize # <-- this is also pretty smelly
#search = #search_results[model]
end
private
def search_params
params.require(:q, :model)
end
Then in your view you can just access #search.

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

false vs 0 while serving object in database Rails

There is the following code:
class BeautySalonCategory < ActiveRecord::Base
before_create :set_default_values
protected
def set_default_values
self.available = false
end
end
When I use Rails console and input 'BeautySalonCategory.create!(name: "Some name")' I get the following error:
ActiveRecord::RecordNotSaved
But if I change 'self.available = false' to 'self.available = 0' then no errors won't appear. Why? Thanks.
There's two things going on: Rails expects your before_create handlers to return a non-false value when they successfully run, and the result of an a = b statement in Ruby is b. So your self.available = false version returns false, indicating to Rails that the before_create failed. If you define your method like this, everything will be fine:
def set_default_values
self.available = false
true
end
(Props to maringan for spotting this in the comments.)

Resources