Artikel ini dibuat berdasarkan pertanyaan pada StackOverflow mengenai implementasi Ruby block. Pada saat implementasi Ruby block, lebih baik menggunakan instance_eval dibandingkan dengan yield jika kita ingin Ruby block dikirimkan tanpa parameter seperti dibawah ini.

Menggunakan yield

class MyClass
  def initialize
    @my_array = []
  end

  def elements
    block_given? ? yield(self) : @my_array
  end

  def add_element( text )
    @my_array << text
  end
end

# error
my_object = MyClass.new
my_object.elements {
  add_element "hello"
  add_element "world"
} # => NoMethodError: undefined method `add_element' for main:Object
p my_object.elements # => []

# ok
my_object = MyClass.new
my_object.elements { |a|
  a.add_element "hello"
  a.add_element "world"
}
p my_object.elements  # => ["hello", "world"]

Menggunakan instance_eval

class MyClass
  def initialize
    @my_array = []
  end

  def elements(&block)
    block_given? ? instance_eval(&block) : @my_array
  end

  def add_element( text )
    @my_array << text
  end
end

# ok, no error
my_object = MyClass.new
my_object.elements {
  add_element "hello"
  add_element "world"
}
p my_object.elements # => ["hello", "world"]

# ok too
my_object = MyClass.new
my_object.elements { |a|
  a.add_element "hello"
  a.add_element "world"
}
p my_object.elements # => ["hello", "world"]