Protecting against an undefined chained method
I have a long loop that results in this:
csv_code = CSV.generate do |csv|
c开发者_JS百科sv << ["Product ID","Name", "Url"]
@all_products.each do |product|
if product.page_url("en_US") != nil
turl = product.page_url("en_US")
end
csv << [product.name,product.d_id, turl]
end
end
The method uses products 1-17 works great resulting in a url printed. When I get to my 18th record I have problems
Product.find(18) // product found!
product.find(18).page_url("en_US")
NoMethodError: undefined method `page_url' for nil:NilClass
How can I protect against these undefined events?
url = product.page_url("en_US")
The issue is that a product
is nil
:
undefined method 'page_url' for nil:NilClass". Solution:
(It has nothing to do with page_url
maybe returning nil
.)
Make sure product
can't be nil
: but be wary that this may be a deeper issue. In any case, "fixing" this issue is easy to deal with.
Consider either using a collection restriction (such as Enumerable#reject):
@all_products.reject(&:nil?).each do {
...
}
The above uses the Symbol#to_proc "Rails magic", but could just as easily have been {|x| x.nil?}
as the restriction. The downside is it's not practical to use this for a "no URL" condition per-product although Enumerable#partition could help with that: use the right tool for the job.
Another solution is to expand the conditional check itself:
if product && product.page_url("en_US")
# yay
else
# uhm
end
The short-circuit nature of &&
will ensure page_url
is only invoked upon a truthy value (which excludes nil
).
I also took the liberty of assuming page_url
can't return false
as I find this makes the intent more clear.
Happy coding.
Try this:
product.find(18).try(:page_url, "en_US")
But it's a perf killer.
Are you sure Product.find(18)
doesn't return nil
?
Anyway, you could do:
url = product.nil? ? "no_url" : product.page_url("en_US")
精彩评论