I very much dislike the respond_to case-statement style of handling
multiple formats. If you have a class that has the same case
statement in most of its methods, then it should be broken up into
multiple classes. Case statements to select behavior that way are
redundant in an object-oriented language.
I've been mulling over a cleaner way of replacing respond_to with
either a superclass and subclasses, or a class and modules. I've
been trying to work that out in Rails, but if it's a useful design it
should port over to Merb pretty easily. I do like how you break out
the provides() method, but I think we can get there another way with
less work. I don't mean to be cryptic or anything, but I haven't
worked out my ideas well enough to say anything really specific about
them yet. Now that you've reminded me again about this issue I'll
see if I can get something sorted out soon.
--josh
On Sep 19, 2007, at 10:00 PM, Michael D. Ivey wrote:
> 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.
--
Josh Susser
http://blog.hasmanythrough.com
_______________________________________________
Merb-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/merb-devel