From 3f78de67b5827ee47d738a1dc96518f24bbb0129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 29 Aug 2009 17:48:11 +0200 Subject: Ensure that blocks are also handled inside the responder. --- .../lib/action_controller/metal/mime_responds.rb | 34 ++++++++++------------ .../lib/action_controller/metal/responder.rb | 25 ++++++++++++---- actionpack/test/controller/mime_responds_test.rb | 7 +++++ 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 6a32aeae24..3026067868 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -178,7 +178,10 @@ module ActionController #:nodoc: # def respond_to(*mimes, &block) raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given? - collect_mimes_for_render(mimes, block){ default_render } + + if response = retrieve_response_from_mimes(mimes, &block) + response.call + end end # respond_with wraps a resource around a responder for default representation. @@ -211,8 +214,9 @@ module ActionController #:nodoc: # a proc to it. # def respond_with(*resources, &block) - collect_mimes_for_render([], block) do + if response = retrieve_response_from_mimes([], &block) options = resources.extract_options! + options.merge!(:default_response => response) (options.delete(:responder) || responder).call(self, resources, options) end end @@ -242,34 +246,29 @@ module ActionController #:nodoc: end end - # Receives a collection of mimes and a block with formats and initialize a - # collector. If a response was added to the collector, uses it to satisfy - # the request, otherwise yields the block given. + # Collects mimes and return the response for the negotiated format. Returns + # nil if :not_acceptable was sent to the client. # - def collect_mimes_for_render(mimes, formats) - collector = Collector.new + def retrieve_response_from_mimes(mimes, &block) + collector = Collector.new { default_render } mimes = collect_mimes_from_class_level if mimes.empty? mimes.each { |mime| collector.send(mime) } - formats.call(collector) if formats + block.call(collector) if block_given? if format = request.negotiate_mime(collector.order) self.formats = [format.to_sym] - - if response = collector.response_for(format) - response.call - else - yield - end + collector.response_for(format) else head :not_acceptable + nil end end class Collector #:nodoc: attr_accessor :order - def initialize - @order, @responses = [], {} + def initialize(&block) + @order, @responses, @default_response = [], {}, block end def any(*args, &block) @@ -283,13 +282,12 @@ module ActionController #:nodoc: def custom(mime_type, &block) mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s) - @order << mime_type @responses[mime_type] ||= block end def response_for(mime) - @responses[mime] || @responses[Mime::ALL] + @responses[mime] || @responses[Mime::ALL] || @default_response end def self.generate_method_for_mime(mime) diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb index ac7f5dafe9..a16ed97131 100644 --- a/actionpack/lib/action_controller/metal/responder.rb +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -79,15 +79,16 @@ module ActionController #:nodoc: # Check polymorphic_url documentation for more examples. # class Responder - attr_reader :controller, :request, :format, :resource, :resource_location, :options + attr_reader :controller, :request, :format, :resource, :resources, :options def initialize(controller, resources, options={}) @controller = controller @request = controller.request @format = controller.formats.first @resource = resources.is_a?(Array) ? resources.last : resources - @resource_location = options[:location] || resources + @resources = resources @options = options + @default_response = options.delete(:default_response) end delegate :head, :render, :redirect_to, :to => :controller @@ -109,7 +110,7 @@ module ActionController #:nodoc: # template. # def to_html - render + default_render rescue ActionView::MissingTemplate if get? raise @@ -125,7 +126,7 @@ module ActionController #:nodoc: # responds to :to_format and display it. # def to_format - render + default_render rescue ActionView::MissingTemplate raise unless resourceful? @@ -148,6 +149,20 @@ module ActionController #:nodoc: resource.respond_to?(:"to_#{format}") end + # Returns the resource location by retrieving it from the options or + # returning the resources array. + # + def resource_location + options[:location] || resources + end + + # If a given response block was given, use it, otherwise call render on + # controller. + # + def default_render + @default_response.call + end + # display is just a shortcut to render a resource with the current format. # # display @user, :status => :ok @@ -166,7 +181,7 @@ module ActionController #:nodoc: # render :xml => @user, :status => :created # def display(resource, given_options={}) - render given_options.merge!(options).merge!(format => resource) + controller.render given_options.merge!(options).merge!(format => resource) end # Check if the resource has errors or not. diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 44536ce54e..93a815adae 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -726,6 +726,13 @@ class RespondWithControllerTest < ActionController::TestCase assert_equal "david", @response.body end + def test_block_inside_respond_with_is_rendered + @controller = InheritedRespondWithController.new + @request.accept = "application/json" + get :index + assert_equal "JSON", @response.body + end + def test_no_double_render_is_raised @request.accept = "text/html" assert_raise ActionView::MissingTemplate do -- cgit v1.2.3