Hommer Smith
Hommer Smith

Reputation: 27852

Difference with open-uri with block and without it

What is the difference between doing:

file = open('myurl')
# Do stuff with file

And doing:

open('myurl') do |file|
 # Do things with file
end

Do I need to close and remove the file when I am not using the block approach? If so, how do I close and remove it? I don't see any close/remove method in the docs

Upvotes: 2

Views: 1126

Answers (1)

Jordan Running
Jordan Running

Reputation: 106027

The documentation for OpenURI is a little opaque to beginners, but the docs for #open can be found here.

Those docs say:

#open returns an IO-like object if block is not given. Otherwise it yields the IO object and return the value of the block.

The key words here are "IO-like object." We can infer from that that the object (in your examples, file), will respond to the #close method.

While the documentation doesn't say so, by looking at the source we can see that #open will return either a StringIO or a Tempfile object, depending on the size of the data returned. OpenURI's internal Buffer class first initializes a StringIO object, but if the size of the output exceeds 10,240 bytes it creates a Tempfile and writes the data to it (to avoid storing large amounts of data in memory). Both StringIO and Tempfile have behavior consistent with IO, so it's good practice (when not passing a block to #open), to call #close on the object in an ensure:

begin
  file = open(url)
  # ...do some work...
ensure
  file.close
end

Code in the ensure section always runs, even if code between begin and ensure raises an exception, so this will, well, ensure that file.close gets called even if an error occurs.

Upvotes: 4

Related Questions