1

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?

4

3 回答 3

2

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().

于 2012-09-17T21:48:20.610 回答
1

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
于 2012-09-17T23:12:19.853 回答
0

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.

于 2012-09-17T22:17:52.243 回答