I started learning Ruby on Rails and found myself confounded by the syntax, so I had to read about somet of the Ruby syntax. I learned the syntax from http://www.cs.auckland
method_call do [`|' expr...`|'] expr...end
Is not limited to iteration functions.
In ruby, any method can take a block as an argument. The block can then be called by the method. In the case of an iterator, the method looks something like this:
def iter
for i in [:x,:y,:z]
yield i
end
end
If you call iter
with a block, it will loop over [:x, :y, :z]
and yield each of them to the block, which can then do whatever you want. e.g. to print them out:
iter { |z| puts z }
You can also use this to hide init and cleanup steps, like opening and closing files. e.g. File.open
. File.open, if it were implemented in pure ruby(it's in C for performance) would do something like this.
def File.open filename, opts
f = File.new filename, opts
yield f
f.close
end
Which is why you can use
File.open 'foobar', 'w' do |f|
f.write 'awesome'
end
respond_to
is similar. It works something like this:( check out the real implementation here)
def respond_to
responder = Responder.new(self)
block.call(responder)
responder.respond
end
It creates a responder object that has methods like html
that take a block and passes it to you. This turns out to be really handy, because it lets you do things like:
def action
@foo = Foo.new params[:foo]
respond_to do |format|
if @foo.save
format.html { redirect_to foo_path @foo }
format.xml { render :xml => @foo.to_xml }
else
flash[:error] = "Foo could not be saved!"
format.html { render :new }
format.xml { render :xml => {:errors => @foo.errors }.to_xml}
end
end
end
See how I change the behavior dependent on save inside the block? Doing this would be much more annoying without it.