NoMethodError (undefined method `<' for nil:NilClass): - ruby-on-rails

This is the error I have received:
NoMethodError (undefined method `<' for nil:NilClass):
app/controllers/concerns/withdraws/withdrawable.rb:20:in `create'
This is the part of the code in question:
def create
#withdraw = model_kls.new(withdraw_params)
#verified = current_user.id_document_verified?
#local_sum = params[:withdraw][:sum]
if !#local_sum
render text: I18n.t('private.withdraws.create.amount_empty_error'), status: 403
return
end
if !#verified && channel.currency_obj.withdraw_limit < #local_sum <<<<<- Here is the error
render text: I18n.t('private.withdraws.create.unverified_withdraw_limit_error', limit: channel.currency_obj.withdraw_limit), status: 403
return
end
That's all my code:
https://github.com/DigitalCoin1/Spero-Exchange
The error in question is in this file:
https://github.com/DigitalCoin1/Spero-Exchange/blob/rebuild-peatio/app/controllers/concerns/withdraws/withdrawable.rb
Thank you very much!!!

Remember, (almost) everything is Ruby is an object... including nil.
Keeping that in mind, consider what happens when you call a method that doesn't exist on nil:
irb(main):001:0> nil.something
Traceback (most recent call last):
2: from /Users/scott/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
1: from (irb):1
NoMethodError (undefined method `something' for nil:NilClass)
Additionally, in Ruby operators such as >, <, and == are actually method calls. So, for example, an instance of Integer such as 3 has a method defined on it called < and when you call 3 < 4, that calls the method on that instance. This works like that because in Ruby you can omit parentheses when making method calls. For example:
irb(main):001:0> 3 < 4
=> true
irb(main):002:0> 3.<(4)
=> true
So putting these two examples together:
irb(main):014:0> nil < 4
Traceback (most recent call last):
2: from /Users/scott/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
1: from (irb):14
NoMethodError (undefined method `<' for nil:NilClass)
Now, let's take a look at your code.
You're getting the exception:
NoMethodError (undefined method `<' for nil:NilClass)
On this line:
!#verified && channel.currency_obj.withdraw_limit < #local_sum
Looking at this code, you are only calling < in one place. This means that whatever is to the left of it (channel.currency_obj.withdraw_limit) must be nil.
There are a few ways we can fix this... The best way, (in my opinion) is to make sure that channel.currency_obj can never be nil. I unfortunately don't have enough code to show you exactly how to do that, so let's look at some other options...
We can use Ruby 2.3+'s safe navigation operator (&.) -- but it's a little weird to use with an operator like <.
channel.currency_obj.withdraw_limit&. < #local_sum
Note: in this example the expression will evaluate to nil and because nil is falsey the conditional will return false.
Or, we can just add another expression to our conditional to check for nil:
!#verified && channel.currency_obj.withdraw_limit && channel.currency_obj.withdraw_limit < #local_sum

The error happened when channel.currency_obj.withdraw_limit return nil or #local_sum is nil.
And it can't compare nil value.
You must check #local_sum again, and make sure that it have a value. Or channel.currency_obj.withdraw_limit make sure that it have a value.
But i guess that channel.currency_obj.withdraw_limit return nil.
That your problem.

NoMethodError (undefined method `<' for nil:NilClass):
app/controllers/concerns/withdraws/withdrawable.rb:20:in `create'
This error denotes that it is trying to compare < for a nil value.
Can you please print and check channel.currency_obj.withdraw_limit and #local_sum before the error statement.
To avoid nil errors you can include nil check.
if channel.currency_obj.withdraw_limit != nil and #local_sum != nil

Related

Unique undefined method error rails

I have a really unique case of the 'undefined method error' in Rails. I have a Task Order model that has the attributes "obligatedAmount" and "awardAmount". When creating a new Task Order, one of my business rules is the "obligatedAmount" cannot be greater than the "awardAmount". So ensure this, I made a custom validation:
validate :check_amount_obilgated
validates_presence_of :awardAmount
validates_presence_of :obligatedAmount
def check_amount_obilgated #cannot be greater than contract award amount
if obligatedAmount > awardAmount
errors.add(:obligatedAmount, "The Obligated Amount cannot be greater than the Award Amount")
end
end
This works fine. HOWEVER, if I make a new Task Order and I leave the "obligatedAmount" OR the "awardAmount"empty, I Rails takes me to the error page with the error snippet:
undefined method `>' for nil:NilClass'
def check_amount_obilgated #cannot be greater than contract award amount
if obligatedAmount > awardAmount
errors.add(:obligatedAmount, "The Obligated Amount cannot be greater than the Award Amount")
end
end
So I guess the issue is that if one or both values are missing, the ">" operator cannot work. However, I put in the validates_presence_of :awardAmount and :obligatedAmount... is there any way I can get the validations to kick in first or is there any way around this error? Please let me know. Thank you!!
Use to_i to convert nil to zero
def check_amount_obilgated #cannot be greater than contract award amount
if obligatedAmount.to_i > awardAmount.to_i
errors.add(:obligatedAmount, "The Obligated Amount cannot be greater than the Award Amount")
end
end
So the explaination is pretty straightforward. The > operator is defined on the Fixnum class. NilClass does not have > defined, so it will throw an undefined method error. If nil is passed to the valid call, you'll get a comparison error as nil can't be coerced implicitly to a Fixnum.
A quick check in irb shows the errors you can expect if nil shows up in either the right-hand or left-hand operand:
2.1.2 :001 > 1 > nil
ArgumentError: comparison of Fixnum with nil failed
from (irb):1:in `>'
from (irb):1
from /Users/hungerandthirst/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :002 > nil > 1
NoMethodError: undefined method `>' for nil:NilClass
from (irb):2
from /Users/hungerandthirst/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
A simple cast to_i on both operands will result in the values being zero when nil and you will always be able to run the comparison.
2.1.2 :005 > nil.to_i
=> 0
So in your code, do:
obligatedAmount.to_i > awardAmount.to_i

params[...] comparison raises "undefined method `>' for nil:NilClass" error in ruby on rails

I want to check below:
if params[:hidval] > "0"
OR
if !params[:hidval] < "1"
But it gave me error below:
undefined method `>' for nil:NilClass
How do I check above conditions in ruby on rails?
The error message says it all. Make sure, the param actually exists. You try to compare nothing (NilClass) with a number. (which is actually a string, that will be your next problem)
Probably correct would be:
if params[:hidval].present? && params[:hidval] > 0
# Do something ...
end
As of Ruby 2.3, you can use the Safe Navigation Operator &. to streamline this:
irb(main):028:0> 5 > 0
=> true
irb(main):029:0> nil > 0
NoMethodError: undefined method '>' for nil:NilClass
from (irb):29
irb(main):030:0> 5 &.> 0
=> true
irb(main):031:0> nil &.> 0
=> nil
irb(main):032:0> 5 &.> 99
=> false
This will typically get you what you want (e.g. conditional branching) since nil is falsey. But keep that in mind if you actually depend on an exact false value.
&. means to only call the trailing method if the leading object is not null. It makes a lot more sense in a chained method call like:
user&.deactivate!
But, since the greater-than operator > is actually a method in Ruby, it works here as well.
Personally, I'm not convinced the painful aesthetics of params[:hidval] &.> "0" makes this worthwhile...but that's just a question of style.
Try this code
if params[:hidval].present?
if params[:hidval].to_i > 0
# Greater than 0 condition
else
# Less than equal to 0 condition
end
end
Re-reading this question, I realize I missed the mark on my first answer. It side-stepped the problem without addressing it.
The real problem you saw this error is that you probably put ! in the wrong place.
If you meant, if it is not less than "1", then you should write:
if !( params[:hidval] < "1" )
This compares hidval and "1" and THEN negates the result.
What you posted:
if !params[:hidval] < "1"
...first negates hidval (usually resulting in false) and then compares false (or possibly true) to see if it is less than "1". Not only does comparing false to a string not make much sense, you'll actually get you this error:
NoMethodError (undefined method `<' for false:FalseClass)

Ruby - NoMethodError (undefined method for nil:NilClass):

I'm having some difficulty trying to figure out what I am doing wrong. My ActiveRecord query is returning nil which I think is causing NoMethodError to be raised.
Here's what I have:
#number_exclude_list = ["1234567890", "2223334545"]
#available_number = UserNumber.where.not(:user_num => #number_exclude_list)
Which returns an empty set of rows:
=> #<ActiveRecord::Relation []>
So, then I have:
if (#available_number.empty?)
inform_user_empty
else
do_my_other_function
But, I get:
`NoMethodError (undefined method 'inform_user_empty' for nil:NilClass)`
I have tried: #available_number.blank? and `#available_number.nil?
And I still get the same NoMethodError. Any ideas on what I am doing wrong here?
The exception text NoMethodError (undefined method 'inform_user_empty' for nil:NilClass) says that is was a call to instance method #inform_user_empty of the nil class'es instance, and since nil has no instance method ruby interpreter throwed that exception. I see the two main reason for it:
self keyword variable has nil value, I believe not in the reason, because you do a call from a controller, as you've said ApplicationController. To make sure that self isn't nil, change the code to the following one:
if #available_number.empty?
p self
self.inform_user_empty
rerun the action, and look at the result.
The exception has been thrown from another place. So you have to specify the full trace log in your post.
Please run the below line in your console:
#available_number = UserNumber.where.not(:user_num => #number_exclude_list)
it returns an ArgumentError: wrong number of arguments (0 for 1+) since it is not the way to check NOT IN condition in Rails activerecord.
Replace it with:
User.where('user_num NOT IN (?)',#number_exclude_list)
and then do:
if #available_number == nil
inform_user_empty
else
do_my_other_function
end
Hoep that will resolve the issue. Please let me know if it really helped you.

NoMethodError: undefined method `to_d' for nil:NilClass

NoMethodError: undefined method `to_d' for nil:NilClass
this seems to be inconsistent with other "to_"
eg with Rails 3.2.14, and ruby 1.9.3p362:
1.9.3p362 :055 > nil.to_f
=> 0.0
1.9.3p362 :056 > nil.to_d
NoMethodError: undefined method `to_d' for nil:NilClass
1.9.3p362 :057 > nil.to_s
=> ""
1.9.3p362 :058 > nil.to_i
=> 0
it means that when ever i might want to convert to big decimal that i first have to make sure the value is not nil and assign it a 0 value anyway... so... comments on what is the best way to make this consistent? and should i consider this a bug?
to_d isn't part of core Ruby. It's part of the BigDecimal package; specifically you get it when you require "bigdecimal/util". It monkey-patches itself into some of the core classes, but as you've discovered, not all of them.
If you just want nil.to_d to return nil (which seems like the only sensible thing for it to return), you can monkey-patch it yourself:
class NilClass
def to_d
nil
end
end
irb(main):015:0> nil.to_d
=> nil
If you want it to return an actual BigDecimal with value 0, then return BigDecimal.new(0) instead, but I think nil should be nil.
or
(nil.try(:to_d) || 0) + value
You can always use #try, which will return nil if the receiver is nil, or call the method if the receiver is not nil
nil.try :to_d
#=> nil
1.try :to_d
#=> #<BigDecimal:7ffe8e39c1e8,'0.1E1',9(36)>
you're probably better off converting to a string first if that's what you need
BigDecimal.new(amount.to_s)

How to catch an "undefined method `[]' for nil:NilClass" error?

I get an nested array from facebook via omniauth and wanna check if it's empty?/nil?/exists?
the depending line looks like:
unless omniauth['extra']['raw_info']['location']['name'].nil?
This should check if this part of the array is empty or exists.
But always this error was thrown:
undefined method `[]' for nil:NilClass
Do I check arrays wrong?
I tried it with "has_key" "nil?" "empty?" "exists?" "blank?"
But no one of these works!
Please help me, many thanks in advance!
Ideally you should check each nested level to see if it is nil, however, this will also work.
unless (omniauth['extra']['raw_info']['location']['name'] rescue nil).nil?
You can also rescue the NoMethodError specifically.
This error is raised because one of the hash values in the chain of omniauth['extra']['raw_info']['location']['name'].nil? returns nil and it is not the last call ['name'].
If for example omniauth['extra']['raw_info'] returns nil, you're actually trying to call nil['location'] which raises an error in ruby.
You can catch this error simply:
res = omniauth['extra']['raw_info']['location']['name'].nil? rescue true
unless res
#your code here
end
Please notice that the code block above will fill the variable res with true if the ['name'] hash value is nil or any other hash value in the chain returns nil.
A bit late to the party, but, as pointed in this answer, Ruby 2.3.0 introduced a new method called dig, which would return nil if one of the chained keys is nil. Your omniauth auth hash could then be presented as:
omniauth = {
...
"extra"=>{ "raw_info"=>
{ "location"=>"New York",
"gravatar_id"=>"123456789"}}
...
}
omniauth.dig('extra',
'raw_info',
'location',
'name',
'foo',
'bar',
'baz') #<= nil

Resources