Search code examples
rubyiteratorrubygemsruby-on-rails-5iteration

Can you yield inside a code block in Ruby?


I'm currently learning Ruby and doing so by reading the popular book "The well-grounded Rubyist". I do understand code blocks pretty decently, or so I thought, until I hit this code example from the book on page 191:

open_user_file do |filename|
   fh = File.open(filename)
   yield fh
   fh.close
   rescue
     puts "Couldn't open your file"
end

Now the thing I do no quite get here is, whom do I yield to when yielding within a code block? The way I understood it is that if you call a method that can yield and you provided a code block, the method will yield to your code block (maybe even with arguments), your code block executes and then gives control back to the method. But here in this code example we do not yield within the method, but in the code block. Could someone explain to me how this works and how a construct like this may look like? Any clarifications are appreciated!

(P.S. please don't tell me "You shouldn't do this". I am not asking because I want to do this in production code, I merely want to understand the inner workings of Ruby in-depth.)


Solution

  • The code you have there does in fact not work, because there is no block to yield to.

    You will get a LocalJumpError, which gets swallowed by the catch-all rescue, and thus it will look like there is a problem with the file, when in fact, there is actually a programming error. (Teachable moment: never ever do a blanket catch-all rescue, always rescue only exactly those exceptions you want to handle.)