diff options
Diffstat (limited to 'actionpack/lib/action_controller')
4 files changed, 62 insertions, 39 deletions
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 950105e63f..3026067868 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -179,21 +179,8 @@ 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? - collector = Collector.new - mimes = collect_mimes_from_class_level if mimes.empty? - 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 response = collector.response_for(format) - response.call - else - default_render - end - else - head :not_acceptable + if response = retrieve_response_from_mimes(mimes, &block) + response.call end end @@ -227,10 +214,11 @@ module ActionController #:nodoc: # a proc to it. # def respond_with(*resources, &block) - respond_to(&block) - rescue ActionView::MissingTemplate - options = resources.extract_options! - (options.delete(:responder) || responder).call(self, resources, options) + 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 def responder @@ -258,11 +246,29 @@ module ActionController #:nodoc: end end + # Collects mimes and return the response for the negotiated format. Returns + # nil if :not_acceptable was sent to the client. + # + 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) } + block.call(collector) if block_given? + + if format = request.negotiate_mime(collector.order) + self.formats = [format.to_sym] + 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) @@ -276,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 fc01a0924a..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,8 +110,10 @@ module ActionController #:nodoc: # template. # def to_html + default_render + rescue ActionView::MissingTemplate if get? - render + raise elsif has_errors? render :action => default_action else @@ -118,12 +121,14 @@ module ActionController #:nodoc: end end - # All others formats try to render the resource given instead. For this - # purpose a helper called display as a shortcut to render a resource with - # the current format. + # All others formats follow the procedure below. First we try to render a + # template, if the template is not available, we verify if the resource + # responds to :to_format and display it. # def to_format - return render unless resourceful? + default_render + rescue ActionView::MissingTemplate + raise unless resourceful? if get? display resource @@ -144,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 @@ -162,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/lib/action_controller/testing/integration.rb b/actionpack/lib/action_controller/testing/integration.rb index 5cb0f48f82..e7104e5c3d 100644 --- a/actionpack/lib/action_controller/testing/integration.rb +++ b/actionpack/lib/action_controller/testing/integration.rb @@ -2,9 +2,7 @@ require 'stringio' require 'uri' require 'active_support/test_case' require 'active_support/core_ext/object/metaclass' - -require 'rack/mock_session' -require 'rack/test/cookie_jar' +require 'rack/test' module ActionController module Integration #:nodoc: @@ -251,7 +249,7 @@ module ActionController end end - opts = { + env = { :method => method, :params => parameters, @@ -267,18 +265,19 @@ module ActionController "CONTENT_TYPE" => "application/x-www-form-urlencoded", "HTTP_ACCEPT" => accept } - env = Rack::MockRequest.env_for(path, opts) (rack_environment || {}).each do |key, value| env[key] = value end + session = Rack::Test::Session.new(@mock_session) + @controller = ActionController::Base.capture_instantiation do - @mock_session.request(URI.parse(path), env) + session.request(path, env) end @request_count += 1 - @request = ActionDispatch::Request.new(env) + @request = ActionDispatch::Request.new(session.last_request.env) @response = ActionDispatch::TestResponse.from_response(@mock_session.last_response) @html_document = nil diff --git a/actionpack/lib/action_controller/testing/process.rb b/actionpack/lib/action_controller/testing/process.rb index 4185b803c5..5fb244e3eb 100644 --- a/actionpack/lib/action_controller/testing/process.rb +++ b/actionpack/lib/action_controller/testing/process.rb @@ -84,7 +84,7 @@ module ActionController #:nodoc: # # Pass a true third parameter to ensure the uploaded file is opened in binary mode (only required for Windows): # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(ActionController::TestCase.fixture_path + '/files/spongebob.png', 'image/png', :binary) - TestUploadedFile = Rack::Utils::Multipart::UploadedFile + TestUploadedFile = Rack::Test::UploadedFile module TestProcess def self.included(base) |