Permalink
Browse files

Fail informatively in #respond_with when no appropriate #api_behavior…

… renderer is available.

Currently if a user calls #respond_with(csvable), but has not csv
renderer available, Responder will just run through the default render
behavior twice, raising ActionView::MissingTemplate both times.

This changes ActionController::Metal::Responder#api_behavior to check
in advance whether there is a renderer available, and raise
ActionController::MissingRenderer if not.
  • Loading branch information...
Empact committed Aug 18, 2013
1 parent 6776980 commit f84c6201dd592f9ef0b5e8473951bf6ceec213e6
@@ -6,6 +6,13 @@ def self.add_renderer(key, &block)
Renderers.add(key, &block)
end
+ class MissingRenderer < LoadError
+ def initialize(format)
+ @format = format
+ super("No renderer defined for format: #{@format}")
+ end
+ end
+
module Renderers
extend ActiveSupport::Concern
@@ -202,6 +202,7 @@ def navigation_behavior(error)
# This is the common behavior for formats associated with APIs, such as :xml and :json.
def api_behavior(error)
raise error unless resourceful?
+ raise MissingRenderer.new(format) unless has_renderer?
if get?
display resource
@@ -269,6 +270,11 @@ def has_errors?
resource.respond_to?(:errors) && !resource.errors.empty?
end
+ # Check whether the neceessary Renderer is available
+ def has_renderer?
+ Renderers::RENDERERS.include?(format)
+ end
+
# By default, render the <code>:edit</code> action for HTML requests with errors, unless
# the verb was POST.
#
@@ -107,6 +107,20 @@ def create
end
end
+class CsvRespondWithController < ActionController::Base
+ respond_to :csv
+
+ class RespondWithCsv
+ def to_csv
+ "c,s,v"
+ end
+ end
+
+ def index
+ respond_with(RespondWithCsv.new)
+ end
+end
+
class EmptyRespondWithController < ActionController::Base
def index
respond_with(Customer.new("david", 13))
@@ -607,6 +621,23 @@ def test_using_resource_with_set_responder
RespondWithController.responder = ActionController::Responder
end
+ def test_uses_renderer_if_an_api_behavior
+ ActionController::Renderers.add :csv do |obj, options|
+ send_data obj.to_csv, type: Mime::CSV
+ end
+ @controller = CsvRespondWithController.new
+ get :index, format: 'csv'
+ assert_equal Mime::CSV, @response.content_type
+ assert_equal "c,s,v", @response.body
+ end
+
+ def test_raises_missing_renderer_if_an_api_behavior_with_no_renderer
+ @controller = CsvRespondWithController.new
+ assert_raise ActionController::MissingRenderer do
+ get :index, format: 'csv'
+ end
+ end
+
def test_error_is_raised_if_no_respond_to_is_declared_and_respond_with_is_called
@controller = EmptyRespondWithController.new
@request.accept = "*/*"

0 comments on commit f84c620

Please sign in to comment.