respond_to do |format|
format.html { |x| puts x }
format.json { |x| puts x }
end
The inner part is understandable, since I knew code blocks from my Clipper 5 days. For each different format, a different code block is executed. But I simply couldn't understand the outer part. Was this do...end a loop? A disguised switch? Where "format" comes from? The "respond_to" seems to be a method, but the "parameter" would be the "do...end" code. Too strange.
And this pattern appears in several places in Rails scaffold-generated code. I couldn't let that pass without understanding how it really works.
After a lot of Googling, I finally got it at dawn. I have added some fake additional code to make it more understandable:
class Response
def html(&code_block)
# This response is HTML, so method does something
code_block.call("<html>...</html>")
end
def json(&code_block)
# This response is not JSON, so method does nothing
nil
end
end
def respond_to( &code_block )
code_block.call( Response.new )
end
respond_to do |format|
format.html { |x| puts x }
format.json { |x| puts x }
end
First, the do...end block that follows "respond_to" is not a loop, is not a disguised switch. It is simply a block of code that will be executed top to down, normally.
The magic here is: the do...end block is a code block exactly like {|x| ... }, which allows it to be passed as a parameter to respond_to method. So the do...end block is not executed right away, but only if respond_to does it.
Inside respond_to method, the code block is actually called, passing a Response object as a parameter. This Response object will be passed as "format" back to the code block. But it means that both Response.html and Response.json methods will be called in sequence, and we probably want only one of the formats in output.
The second magic is that Response object passed to code block is rigged to answer only to the method that is the desired output format. So, looking at my fake Response class, you can see that "html" method does something, while "json" method is a no-op. In Rails, of course this magic is done by the internal response dispatcher.
The third magic is that Rsponse.html method again receives a code block from user code -- in the case, {|x| puts x}, and calls it to render the HTML page the way the user wants to.
It seemed unnecessarly convoluted the first time I could see the whole picture, I would like to know the actual performance of that, but I guess people just get used to that, and the final syntax for different output formats is quite handy and terse.