Posted almost 3 years ago. Visible to the public. Repeats. Linked content.

Ruby: A small summary of what return, break and next means for blocks


  • Use return to return from a method. return accepts a value that will be the return value of the method call.
  • Use break to quit from a block and from the method that yielded to the block. break accepts a value that supplies the result of the expression it is “breaking” out of.
  • Use next to skip the rest of the current iteration. next accepts an argument that will be the result of that block iteration.

The following method will serve as an example in the details below:

def example puts yield puts 'done' return 'example' end # Intended usage & output: example { 'hallo welt' } # hallo welt # done # => 'example'

Return within a block

Return is only valid inside a method. If you use it inside a block or not is not relevant. Return lets you jump out of a method and returns nil or an argument.

return # => LocalJumpError: unexpected return example { return 4 } # => LocalJumpError: unexpected return def test example { return 4 } return 'test' end test # => 4

Note how test returns the return value from the block; neither code after the example invocation (returning "test") nor code after the yield inside example (putsing "done", returning "example") are executed. As you always knew, and in blocks too: return exits that method NOW.

If you nest blocks return is still jumping out of the method (and not out of the first block or something similar).

def test [1, 2, 3].each do |counter| example { return counter } end return 'test' end test # => 1

Conclusion: return has no special meaning in blocks, but it can be misunderstood as "return from block", which is wrong. See Fun with Ruby: Returning in blocks "overwrites" outside return values for an example.

Break within a block

Break is only valid within a block. It lets you jump out of a block and returns nil or the provided argument to the caller.

break # => SyntaxError: Can't escape from eval with break example { break 'break' } # => 'break'

Note how break changes the return value of the method yielding to the block from example to its argument. Also, the code after the yield in example is not executed! Probably, this behavior was designed to enable programmers writing their own iterators (like while or loop) as methods and still get all the keyword love from Ruby.

As a side note, using break also could indicate a code smell (when we look at what was said above about the expected return value):

# bad [1, 2, 3].each { |counter| break counter if counter.even? } # => 2 [1, 3].each { |counter| break counter if counter.even? } # => [1, 3] # good [1, 2, 3].find(&:even?) # => 2 [1, 3].find(&:even?) # => nil

Next within a block

Use next to skip the rest of the current iteration. next accepts an argument that can be used as the result of the current block iteration.

next # => SyntaxError: (irb):24: Can't escape from eval with next example { next 'next' } 'next' 'done' # => 'example'

Note how next exits the block returning its argument as block return value, but the example method still gets to continue with its code after the yield.

A real world example could be logging on user creation without changing the return value:

def save_user do |saved| next unless saved Rails.log("User was created, we have #{user.count} users now!") end end save_user # User was created, we have #{user.count} users now! # => true

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Emanuel De
Last edit:
2 months ago
by Tobias Kraze
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Emanuel De to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more