confusion on respond_to do |format| execution sequence

45 views
Skip to first unread message

Warren Zhang

unread,
Jan 3, 2014, 3:26:20 PM1/3/14
to rubyonra...@googlegroups.com
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.

--
Posted via http://www.ruby-forum.com/.

James Kwame

unread,
Jan 4, 2014, 8:02:12 AM1/4/14
to rubyonra...@googlegroups.com
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

Frederick Cheung

unread,
Jan 4, 2014, 8:16:38 AM1/4/14
to rubyonra...@googlegroups.com


On Friday, January 3, 2014 8:26:20 PM UTC, Ruby-Forum.com User wrote:

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
Reply all
Reply to author
Forward
0 new messages