tags:

views:

113

answers:

2
  def any?
    if block_given?
      method_missing(:any?) { |*block_args| yield(*block_args) }
    else
      !empty?
    end
  end

In this code from ActiveRecord, what is the purpose of a yield statement that exists within a block?

+7  A: 

Basically if the current method has been given a code-block (by the caller, when it was invoked), the yield executes the code block passing in the specified parameters.

[1,2,3,4,5].each { |x| puts x }

Now { |x| puts x} is the code-block (x is a parameter) passed to the each method of Array. The Array#each implementation would iterate over itself and call your block multiple times with x = each_element

pseudocode
def each
  #iterate over yourself
    yield( current_element )
end

Hence it results

1
2
3
4
5

The *block_args is a Ruby way to accept an unknown number of parameters as an array. The caller can pass in blocks with different number of arguments.

Finally let's see what yield within a block does.

class MyClass
  def print_table(array, &block)
    array.each{|x| yield x}
  end
end

MyClass.new.print_table( [1,2,3,4,5] ) { |array_element| 
    10.times{|i| puts "#{i} x {array_element} = #{i*array_element}" }
    puts "-----END OF TABLE----"
  }

Here Array#each yields each element to the block given to MyClass#print_table...

Gishu
+4  A: 

It does not mean anything special. It's just a yield like any other yield.

def test_method
  ["a", "b", "c"].map {|i| yield(i) }
end

p test_method {|i| i.upcase }
# => ["A", "B", "C"]

In the code snippet from active record, the purpose is to yield every time the block of any? is called.

August Lilleaas
It helps to remember that the block includes the scope of the surrounding method — so it really is exactly the same as yielding anywhere else.
Chuck
`yield` doesn't care about scope anyway.
August Lilleaas