2

I have some difficulties for using Ruby block, passing in a method.

As in the following case, I would like to display each element of @array, from Box instance (using .each method):

class Box
  def initialize
    @array = [:foo, :bar]
  end

  def each(&block)
    # well, hm..
  end
end

a = Box.new
a.each { |element| puts element }

2 Answers 2

7

You really just need to delegate to the each method on @array and pass it the block. Additionally, you can include the Enumerable mix-in to gain access to the methods it provides (e.g. map, inject, etc...):

class Box
  include Enumerable

  def initialize
    @array = [:foo, :bar]
  end

  def each(&block)
    @array.each(&block)
  end
end

More information on the Enumerable module is available in the documentation.

Sign up to request clarification or add additional context in comments.

1 Comment

The Forwardable library is another way to handle simple delegation: require 'forwardable', and then inside Box: extend Forwardable and def_delegator(:@array, :each)
1

For this simple example, you actually aren't required to pass the block explicitly:

def each                  
  @array.each{|e| yield e}
end

Passing the block (which is a Proc object) explicitly allows you to test it for things, like the number of arguments that it expects:

class Box
  ...    
  def each(&block)
    @array.each do |e|
      case block.arity
      when 0
        yield
      when 1
        yield e
      when 2
        yield e, :baz
      else
        yield
      end
    end
  end
end

a = Box.new
a.each { puts "nothing" }              # displays "nothing, nothing"
a.each { |e| puts e }                  # displays "foo, bar"
a.each { |e1, e2| puts "#{e1} #{e2}" } # displays "foo baz, bar baz" 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.