Ez (or someone) asked on #merb tonight whether respond_to was the  
right API for
what it does.  After some discussion and pasties, I offer the  
following proposed
API for content negotiation and response format selection:

First, what does respond_to do right now?  I see at as performing 3  
distinct
operations:
   1. parse params[:format] and the accepts header to find out what  
format the
      client wants
   2. look at all the calls to the responder to see what formats the  
action
      provides
   3. reconcile 1 and 2 and pick a format

I propose that we split #2 and #3 into explicit steps.

Here's a sample controller using the new API:

class ManyFormats < Application
   # controllers provide :html by default, so this is implied:
   provides :html

   # every action in this controller also provides :xml and :txt
   provides :xml, :txt

   def index
     # index also provides :js
     provides :js

     # this is smart, and based on all the things
     # currently provided and all the things the client
     # accepts, returns a Symbol for the response format
     case request.format
     when :html, :txt
       render
     when :xml
       SomeClass.to_xml
     when :js
       "Object.new()"
     end
   end

   def textonlyaction
     only_provides :txt
     # this wipes out :html and :xml from the controller-level
     # declarations
     render
   end
end


Win #1: respond_to is no longer a magic black box, we have explicit  
definition of
   our formats and explicit flow control of our rendering

Win #2: in the case where most/all formats use templates, we get  
simpler code:

class CurrentWay < Application
   def index
     respond_to do |fmt|
       fmt.html { render }
       fmt.xml  { render }
       fmt.txt  { render }
       fmt.js   { render }
     end
   end
end

class ProposedWay < Application
   def index
     provides :html, :xml, :txt, :js
     render
   end
end

Win #2.5: Say you wrote an app without respond_to, using only HTML,  
and then
decide you want to support FBML or PBJML.  With the current API you  
have to
modify every single action in every single controller to add a  
respond_to block.
With the proposed API you add "provides :pbjml" to Application and  
add your
templates and it's done.

Added bonus: we can keep a respond_to on top of the provides()  
variables for
people who like it.


Thoughts?  Suggestions?  I'm not too emotionally attached to this  
yet, so feel
free to pick at it or shoot it down.

If it's still deemed viable by the weekend, I'll code it.
_______________________________________________
Merb-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/merb-devel

Reply via email to