Can't understand the example code of block yield with self

In the book

class Foo
  def one
    p 1
  end

  def yield_with_self
    with self yield
  end

  def yield_normally
    yield
  end
end

def one
  p "one one"
end

Foo.new.yield_with_self { one } # => 1
Foo.new.yield_normally { one }  # => "one"

I really don’t understand that the two ‘one’ methods are defined in the same class as instance methods, what is the difference with ‘with self’ or not when yielding?

If I ‘yield’ without ‘with self’, what is the receiver? Why is the second one not the first one called?

Thanks.

The second one method is defined outside of a class, it’s not an instance method.

Using with self yield is convenient for building nice looking DSLs.

Using with self yield you can imagine this DSL being built:

table :users do
  field :name
  field :email
end

While without it you’ll need to provide a method receiver self explicitly to achieve similar result and it looks less clean compared to the first example.

table :users do |t|
  t.field :name
  t.field :email
end
1 Like

In that case there is no implicit receiver and normal rules apply. In your example the block given to Foo#yield_normally method calls one method which is defined at the top level where your call the block.

That’s incorrect. With a normal yield, the implicit receiver is the receiver of the parent scope.

For example, when a block is defined inside a method scope, it inherits the scope of the method:

# reopening previous class definition
class Foo
  def two
    yield_normally { one }
  end
end

Foo.new.two # => 1
2 Likes

Thanks. That’s my fault, didn’t realize the second one is not in the class. (lll¬ω¬)

Yeah, sorry for badly phrased answer. What I’ve meant is there is no implicit receiver given to be used when yield was used instead of with self yield

1 Like