Reputation: 8835
I have the following code:
require 'open-uri'
class CustomException < StandardError;end
def file
f = Kernel.open('http://i.dbastatic.dk/images/2/68/500656768_20012012182407_0401_2.jpg')
return f
rescue => e
raise CustomException.new(e.message)
end
Now if I do the following:
begin
file.body
rescue CustomException
puts "rescued it!"
end
I get:
NoMethodError: undefined method `body' for nil:NilClass
Instead of the the CustomException with the 404 error message from open uri. The strange thing is, that if I instead do:
begin
f = file
f.body
rescue CustomException
puts "rescued it!"
end
Then it works, I get the CustomException, that I can catch, before it's trying to do the .body. I don't get why? And how can I change the file-method to do as I expect?
Upvotes: 1
Views: 1065
Reputation: 27855
Just a little modification to show the problem:
require 'open-uri'
def file
f = Kernel.open('fill_in_some_url_that_returns_a_404')
return f
rescue => e
puts e.message
1 ##<<---- inserted
end
file.body
No you get a undefined method 'body' for 1:Fixnum
Explanation:
Your method does the puts e.message
, but it does not return a result (or in other words: it returns nil
.)
With file.body
you call file
(with the result nil
). and on this result you call body
. But this does not exist for nil
. So you get the error undefined method 'body' for nil:NilClass
If I try
f = file
f.body
I get the same error.
Are you sure, you use the same url in both calls? If you can open your url, the you retrun a valid object.
Actually I can't see your problem without more code.
You could check your code for one thing:
If you define a variable and a method file
, then you get the variable. See example below. Perhaps this is the problem.
file = nil
def file
1
end
file.body #undefined method `body' for nil:NilClass (NoMethodError)
file().body #undefined method `body' for 1:Fixnum (NoMethodError)
To be sure to get the method you can try file()
.
Upvotes: 2
Reputation: 3961
This is probably what you want:
require 'open-uri'
def file(url)
begin
Kernel.open(url)
rescue => e
puts e.message
end
end
Let's try a valid url first:
f = file('http://www.google.com/')
puts f.read if !f.nil?
And now let's try it with a url that returns a 404:
f = file('http://www.google.com/blahblah')
puts f.read if !f.nil?
Edit: Your code raises two errors when called on non-existing URLs. The 'file' method raises a OpenURI::HTTPError, while the 'body' method will raise a NoMethodError because it's called on nil. In your first usage example, you raise those two errors in one statement. In the second usage example, the errors are sequential. Still, they should yield the same result and they do for me.
Upvotes: 0
Reputation: 535169
I think you've confused yourself. The only code you've shown that seems to illustrate the problem is this:
require 'open-uri'
class CustomException < StandardError;end
def file
f = Kernel.open('http://www.google.com/blahblah')
return f
rescue => e
raise CustomException.new(e.message)
end
begin
file.body
rescue CustomException
puts "rescued it!"
end
Well, I ran that code, and I got "rescued it!" Isn't that what one would expect? I never get NoMethodError: undefined method body for nil:NilClass
and I don't believe that you do, either, with the code you show.
So what's the problem, really? Is it that the 404 message isn't getting passed out to stdout? If that's what you wanted, you should have written:
require 'open-uri'
class CustomException < StandardError;end
def file
f = Kernel.open('http://www.google.com/blahblah')
return f
rescue => e
raise CustomException.new(e.message)
end
begin
file.body
rescue CustomException => e
puts "rescued it!", e.message
end
Upvotes: 1