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

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

Summary

  • 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:

Copy
def example(&block) puts block.call 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.

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

Copy
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.

Copy
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):

Copy
# 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.

Copy
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:

Copy
def save_user user.save.tap 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:

Avatar
Emanuel De
Last edit:
almost 2 years ago
by Dominik Schöler
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