aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2009-08-29 17:48:11 +0200
committerJosé Valim <jose.valim@gmail.com>2009-08-29 18:21:19 +0200
commit3f78de67b5827ee47d738a1dc96518f24bbb0129 (patch)
tree767de5f50b123effe1f44d4943915cc9c3328e31 /actionpack
parent684a6b3c71110b018199bf412e485189343e1f6d (diff)
downloadrails-3f78de67b5827ee47d738a1dc96518f24bbb0129.tar.gz
rails-3f78de67b5827ee47d738a1dc96518f24bbb0129.tar.bz2
rails-3f78de67b5827ee47d738a1dc96518f24bbb0129.zip
Ensure that blocks are also handled inside the responder.
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb34
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb25
-rw-r--r--actionpack/test/controller/mime_responds_test.rb7
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 "<name>david</name>", @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