# Ruby block: why doesn't this work?

**URL:** <https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794>\
**Category:** Ruby\
**Created:** [August 2, 2008, 5:05am UTC](https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794 "2008-08-02T05:05:50Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 2, 2008, 5:05am UTC](https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794/1 "2008-08-02T05:05:50Z")

</div>

I’m trying to figure out why my code isn’t doing what I think it  
should…

Basically, I’m trying to create a Info object, and do various things  
to that new object within the block. For what ever reason though, it  
doesn’t look like the code inside the block is getting executed at  
all. (I’m trying to do something that looks kind of like  
activerecord’s create\_table method.)

So… with the print statements in the code, I’d expect to see output  
from the address() and city() methods, but only the initialize method  
prints anything. (I can even put complete nonsense in the address or  
city methods, and nothing happens.)

What am I doing wrong?

Thanks!

class Info  
attr\_accessor :name, :address, :city

def initialize(name)  
@name = name  
print “name: #{name}\n”  
end

def address(value)  
@address = value  
print “address: #{address}\n”  
end

def city(value)  
@city = value  
print “city: #{city}\n”  
end  
end

def info(name)  
Info.new(name)  
end

info :Bob do |i|  
i.address “123 Main St.”  
i.city “Boston, MA”  
end

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 2, 2008, 5:46am UTC](https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794/2 "2008-08-02T05:46:44Z")

</div>

On Friday 01 August 2008 22:04:01 removed\_email\_address@domain.invalid wrote:

> Basically, I’m trying to create a Info object, and do various things  
> to that new object within the block.

What block? You mean this one?

> info :Bob do |i|  
> i.address “123 Main St.”  
> i.city “Boston, MA”  
> end

But the “info” method you’ve defined doesn’t do anything with that  
block:

> def info(name)  
> Info.new(name)  
> end

The block has to be used somewhere within the body of that object.  
(Trying not  
to be too offensive here, but you have exactly zero code in place to do  
anything with the block – which is why nothing happens to the block.)

What you probably want is either to turn it into a local variable:

def info(name, &block)  
p block  
Info.new(name, &block)  
end

Of course, you’d have to change the constructor, too:

def initialize(name)  
@name = name  
yield self  
end

It’s probably easier just to do this:

def info(name)  
i = Info.new(name)  
yield i  
i  
end

Or, if you have at least Ruby 1.8.7, this should work:

def info(name)  
Info.new(name).tap do |i|  
yield i  
end  
end

For what it’s worth, one of the benefits of open source is, if you’re  
wondering “How did they do that??”, you can find out. Here’s a snip from  
create\_table:

def create\_table(table\_name, options = {})  
table\_definition = TableDefinition.new(self)  
…  
yield table\_definition  
…  
end

Object#tap is also a nice illustration of how blocks can work. It’s  
actually  
written in C, but here’s how I fake it on 1.8.6:

class Object  
def tap  
yield self  
self  
end  
end

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 2, 2008, 5:52am UTC](https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794/3 "2008-08-02T05:52:00Z")

</div>

On Fri, Aug 1, 2008 at 11:04 PM, removed\_email\_address@domain.invalid  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> from the address() and city() methods, but only the initialize method  
> prints anything. (I can even put complete nonsense in the address or  
> city methods, and nothing happens.)
> 
> What am I doing wrong?

You need to make the info method call the block. See the code below.

> def address(value)  
> def info(name)  
> i = Info.new(name)  
> yield i  
> i  
> end
> 
> info :Bob do |i|  
> i.address “123 Main St.”  
> i.city “Boston, MA”  
> end

Also this code will currently give you errors because attr\_accessor is  
overwriting your existing method definitions. I recommend using the  
‘fattr’ gem it will give you most of the functionality you desire.

HTH,  
Michael G.  
require ‘rubygems’  
require ‘fattr’

class Info  
fattr :name, :address, :city

def initialize(name)  
self.name = name  
end  
end

def info(name)  
i = Info.new(name)  
yield i  
i  
end

bob = info ‘bob’ do |i|  
i.address “123 foo lane”  
i.city “oz”  
end

puts bob.inspect

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 2, 2008, 6:20am UTC](https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794/4 "2008-08-02T06:20:39Z")

</div>

On Aug 1, 11:45 pm, David M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> For what it’s worth, one of the benefits of open source is, if you’re  
> wondering “How did they do that??”, you can find out. Here’s a snip from  
> create\_table:

Of course I thought of that about 20 minutes after posting. I was  
tired, I guess. 🙂

Thanks

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [August 2, 2008, 6:21am UTC](https://www.ruby-forum.com/t/ruby-block-why-doesnt-this-work/144794/5 "2008-08-02T06:21:14Z")

</div>

On Aug 1, 11:48 pm, Michael G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> bob = info ‘bob’ do |i|  
> i.address “123 foo lane”  
> i.city “oz”  
> end
> 
> puts bob.inspect

The yield worked, thanks.
