Ruby Check If Nil Before Calling Method

What is a better way to check for a nil object before calling a method on it?

Personally, I would use the or operator/keyword:

(financial_document.assets or []).length

Either way, .length is called on an array, giving you 0 if nil.

Ruby how to call a method only when the object is not nil

Depends what is being returned nil doc.css('#content h1') or doc.css('#content h1').text or doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last

Example -

unless doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.nil?
version = doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last.first
end

you can include the proper condition in the unless clause.

From your exception doc.css('#content h1').text.strip.scan( /\(([^>]*)\)/).last seems to be nil. So you can check on this.

Checking if a variable is not nil and not zero in ruby


unless discount.nil? || discount == 0
# ...
end

Ruby: check if object is nil

You seem to have a few questions here, so I'll take a stab at what seems to be the main one:

If you want to see if something is nil, just use .nil? - so in your example, you can just say request.nil?, which returns true if it is nil and false otherwise.

Check if a method/property is defined or not before calling

If there is a config.user defined in every environment, but sometimes it has a value, and sometimes it doesn't, for example, it could be nil or an empty string, you can use present?:

Rails.application.config.user.present?

If it is not defined, you will get a NoMethodError in the case above, so you can rescue it:

begin
user_name = Rails.application.config.user.present? ? Rails.application.config.user : 'some_other_value'
rescue NoMethodError
user_name = 'some_other_value'
end

respond_to? should also work, just make sure you don't confuse it with respond_to, which is a Rails method. It might look something like this:

if Rails.application.config.respond_to?(:user) && Rails.application.config.user.present?
user_name = Rails.application.config.user
else
user_name = 'some_other_value'
end

Nil when calling a method on the variable, but not nil when calling just the variable

Your initialize method assigning @value = value calls the function at def value which returns @nums which has not yet been created in initialize since @nums is created afterwards with nums ||= []; @nums = nums therefore it's nil. This is why .pop won't work.

You've created @nums as an array with nums ||= [] and you're using it with push and pop so why are you checking for the value with value.should == 5 (Integer) when calling value returns an (Array). You would need to write it like value.first.should == 5 or value[0].should == 5 ... otherwise you should change value to return just the element you want

def value
@nums.pop # or @nums[0], or @nums.first or @nums.last however you plan on using it
end

The problem is @value = value in your initialize method. Fix that then you can add the .pop in value.

EDIT

Also your evaluation is calling methods before you've populated @nums with the values. Then the methods "raise" errors. You can't call minus after only one value has been pushed to @nums.

Here's how I would do the flow for splitting the string

# Multiplication and Division need to happen before addition and subtraction
mylist = "1+3*7".split(/([+|-])/)
=> ["1", "+", "3*7"]

# Compute multiplication and division
mylist = mylist.map {|x| !!(x =~ /[*|\/]/) ? eval(x) : x }
=> ["1", "+", 21]

# Do the rest of the addition
eval mylist.join
=> 22

I realize this isn't exactly how you're going about solving this... but I think splitting by order of mathematical sequence will be the right way to go. So first evaluate everything between (), then only multiplication and division, then all addition and subtraction.

EDIT I just looked into what a RPN Calculator is. So don't mind my splitting recommendation as it doesn't apply.

Checking if Nokogiri object is nil before accessing text method

You can use "try" for those cases

fiber = doc.xpath("/*[name()='food']/*[name()='servings']/*
[name()='serving']/*[name()='fiber']").first.try(:text)

It returns nil if first is nil, and it calles text if it's not nil

If you need a default value in case it's nil you can do

fiber = doc.xpath("/*[name()='food']/*[name()='servings']/*
[name()='serving']/*[name()='fiber']").first.try(:text) or 'default'


Related Topics



Leave a reply



Submit