confusion on respond_to do |format| execution sequence

As a new comer for ruby, I feel confused for this snippet:

    respond_to do |format|
      format.html # index.html.erb
      format.xml { render :xml => @posts }
    end

I understand that if format is .html, it will give html response and if
format is .xml, it will give out xml response.

So this block "do |format| ... end" is case switch like in C++. I have
difficulty to understand though in ruby, if the user passing .html, as a
sequential execution (notice in ruby this is not a case switch
statement), what prevent ruby from executing "format.xml { render :xml
=> @posts }" line?

To my feeling (though I know I am wrong for sure), these two lines will
always be executed no matter what kind of format is passed in:

      format.html # index.html.erb
      format.xml { render :xml => @posts }

Please help.

The respond_to is a Ruby block statement
respond_to do |format| creates the variable format and calls html or xml on it

so for each format, carry out some action. In this case, respond to the http request with the appropriate format(html, xml, json)

respond_to do |format|

format.html

format.xml

end

its like iterating using the each do structure. For each post, carry out some action

@posts.each do |post|

post.title

post.body

end

I suggest you lookup/read about Ruby blocks

So this block “do |format| … end” is case switch like in C++. I have

difficulty to understand though in ruby, if the user passing .html, as a

sequential execution (notice in ruby this is not a case switch

statement), what prevent ruby from executing "format.xml { render :xml

=> @posts }" line?

Not really - the block is a ruby block. At some point (or multiple times) the respond_to method will call yield and then execution will transfer to the inside of the block. A method doesn’t have to execute its block at all, and it can also choose to keep it as a Proc object to use later.

To my feeling (though I know I am wrong for sure), these two lines will

always be executed no matter what kind of format is passed in:

  format.html # index.html.erb

  format.xml  { render :xml => @posts }

These 2 lines will both be executed (at least in some sense). When .html is called rails doesn’t render an html response immediately - it merely records that an html response would be acceptable. Similarly when you call .xml it records that xml is an acceptable format, and saves the block passed. So when you get to the end of that block rails knows that html and xml are acceptable formats (in that order) and how it should behave for each one.

Then rails goes over all the acceptable formats looking for one that matches the current request. Only when it finds one that matches will it execute the correspond block (render :xml …) or the corresponding default action (for the html one)

I’ve simplified slightly, but that is the general gist of what is happening (if you are curious action_controller/metal/mime_responds is where this is implemented)

Fred