diff options
Diffstat (limited to 'actionpack/lib/action_controller/metal/mime_responds.rb')
-rw-r--r-- | actionpack/lib/action_controller/metal/mime_responds.rb | 115 |
1 files changed, 38 insertions, 77 deletions
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index f4a4007a43..c8d042acb5 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -177,106 +177,67 @@ module ActionController #:nodoc: # Be sure to check respond_with and respond_to documentation for more examples. # def respond_to(*mimes, &block) - options = mimes.extract_options! raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given? - resource = options.delete(:with) - responder = Responder.new - + collector = Collector.new mimes = collect_mimes_from_class_level if mimes.empty? - mimes.each { |mime| responder.send(mime) } - block.call(responder) if block_given? + mimes.each { |mime| collector.send(mime) } + block.call(collector) if block_given? + + if format = request.negotiate_mime(collector.order) + self.formats = [format.to_sym] - if format = request.negotiate_mime(responder.order) - respond_to_block_or_template_or_resource(format, resource, - options, &responder.response_for(format)) + if response = collector.response_for(format) + response.call + else + default_render + end else head :not_acceptable end end - # respond_with allows you to respond an action with a given resource. It - # requires that you set your class with a :respond_to method with the - # formats allowed: + # respond_with wraps a resource around a responder for default representation. + # First it invokes respond_to, if a response cannot be found (ie. no block + # for the request was given and template was not available), it instantiates + # an ActionController::Responder with the controller and resource. # - # class PeopleController < ApplicationController - # respond_to :html, :xml, :json + # ==== Example # - # def index - # @people = Person.find(:all) - # respond_with(@person) - # end + # def index + # @users = User.all + # respond_with(@users) # end # - # When a request comes with format :xml, the respond_with will first search - # for a template as person/index.xml, if the template is not available, it - # will see if the given resource responds to :to_xml. - # - # If neither are available, it will raise an error. + # It also accepts a block to be given. It's used to overwrite a default + # response: # - # Extra parameters given to respond_with are used when :to_format is invoked. - # This allows you to set status and location for several formats at the same - # time. Consider this restful controller response on create for both xml - # and json formats: + # def destroy + # @user = User.find(params[:id]) + # flash[:notice] = "User was successfully created." if @user.save # - # class PeopleController < ApplicationController - # respond_to :xml, :json - # - # def create - # @person = Person.new(params[:person]) - # - # if @person.save - # respond_with(@person, :status => :ok, :location => person_url(@person)) - # else - # respond_with(@person.errors, :status => :unprocessable_entity) - # end + # respond_with(@user) do |format| + # format.html { render } # end # end # - # Finally, respond_with also accepts blocks, as in respond_to. Let's take - # the same controller and create action above and add common html behavior: - # - # class PeopleController < ApplicationController - # respond_to :html, :xml, :json - # - # def create - # @person = Person.new(params[:person]) - # - # if @person.save - # options = { :status => :ok, :location => person_url(@person) } - # - # respond_with(@person, options) do |format| - # format.html { redirect_to options[:location] } - # end - # else - # respond_with(@person.errors, :status => :unprocessable_entity) do - # format.html { render :action => :new } - # end - # end - # end - # end + # All options given to respond_with are sent to the underlying responder, + # except for the option :responder itself. Since the responder interface + # is quite simple (it just needs to respond to call), you can even give + # a proc to it. # def respond_with(resource, options={}, &block) - respond_to(options.merge!(:with => resource), &block) + respond_to(&block) + rescue ActionView::MissingTemplate + (options.delete(:responder) || responder).call(self, resource, options) end - protected - - def respond_to_block_or_template_or_resource(format, resource, options) - self.formats = [format.to_sym] - return yield if block_given? - - begin - default_render - rescue ActionView::MissingTemplate => e - if resource && resource.respond_to?(:"to_#{format.to_sym}") - render options.merge(format.to_sym => resource) - else - raise e - end - end + def responder + ActionController::Responder end + protected + # Collect mimes declared in the class method respond_to valid for the # current action. # @@ -296,7 +257,7 @@ module ActionController #:nodoc: end end - class Responder #:nodoc: + class Collector #:nodoc: attr_accessor :order def initialize |