Skip to content
Browse files

Refactor Responder to only calculate available mime types. Those are …

…sent to the controller that knows what to do with it (render a block or call default render).

Signed-off-by: Yehuda Katz <wycats@gmail.com>
  • Loading branch information...
1 parent c4d1075 commit 3f445b316d34a49a8b6f27bde72979828baefaa8 @josevalim josevalim committed with wycats Jul 28, 2009
View
129 actionpack/lib/action_controller/base/mime_responds.rb
@@ -1,5 +1,6 @@
module ActionController #:nodoc:
module MimeResponds #:nodoc:
+
# Without web-service support, an action which collects the data for displaying a list of people
# might look something like this:
#
@@ -92,40 +93,39 @@ module MimeResponds #:nodoc:
# environment.rb as follows.
#
# Mime::Type.register "image/jpg", :jpg
- def respond_to(*types, &block)
- raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
- block ||= lambda { |responder| types.each { |type| responder.send(type) } }
- responder = Responder.new(self)
- block.call(responder)
- responder.respond
- end
-
- class Responder #:nodoc:
-
- def initialize(controller)
- @controller = controller
- @request = controller.request
- @response = controller.response
+ def respond_to(*mimes, &block)
+ raise ArgumentError, "respond_to takes either types or a block, never both" unless mimes.any? ^ block
- @mime_type_priority = @request.formats
+ responder = Responder.new(request.formats)
- @order = []
- @responses = {}
+ if block_given?
+ block.call(responder)
+ else
+ mimes.each { |mime| responder.send(mime) }
end
- 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
+ mime = responder.respond
- @responses[mime_type] ||= Proc.new do
- # TODO: Remove this when new base is merged in
- @controller.formats = [mime_type.to_sym]
- @controller.content_type = mime_type
- @controller.template.formats = [mime_type.to_sym]
+ if mime
+ self.formats = [mime.to_sym]
+ self.content_type = mime
+ self.template.formats = [mime.to_sym]
- block_given? ? block.call : @controller.send(:render, :action => @controller.action_name)
+ if response = responder.response_for(mime)
+ response.call
+ else
+ default_render
end
+ else
+ head :not_acceptable
+ end
+ end
+
+ class Responder #:nodoc:
+
+ def initialize(priorities)
+ @mime_type_priority = priorities
+ @order, @responses = [], {}
end
def any(*args, &block)
@@ -135,51 +135,64 @@ def any(*args, &block)
custom(@mime_type_priority.first, &block)
end
end
-
- def self.generate_method_for_mime(mime)
- sym = mime.is_a?(Symbol) ? mime : mime.to_sym
- const = sym.to_s.upcase
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{sym}(&block) # def html(&block)
- custom(Mime::#{const}, &block) # custom(Mime::HTML, &block)
- end # end
- RUBY
+
+ 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
- Mime::SET.each do |mime|
- generate_method_for_mime(mime)
+ def respond
+ available_mimes.first
end
+ def response_for(mime)
+ @responses[mime]
+ end
+
+ # Compares mimes sent by the client (@mime_type_priorities) with the ones
+ # that the user configured in the controller respond_to. Returns them
+ # all in an array.
+ #
+ def available_mimes
+ mimes = []
+
+ @mime_type_priority.each do |priority|
+ if priority == Mime::ALL
+ mimes << @order.first unless mimes.include?(@order.first)
+ elsif @order.include?(priority)
+ mimes << priority
+ end
+ end
+
+ mimes << Mime::ALL if @order.include?(Mime::ALL)
+ mimes
+ end
+
+ protected
+
def method_missing(symbol, &block)
mime_constant = Mime.const_get(symbol.to_s.upcase)
-
+
if Mime::SET.include?(mime_constant)
- self.class.generate_method_for_mime(mime_constant)
+ generate_method_for_mime(mime_constant)
send(symbol, &block)
else
super
end
end
- def respond
- for priority in @mime_type_priority
- if priority == Mime::ALL
- @responses[@order.first].call
- return
- else
- if @responses[priority]
- @responses[priority].call
- return # mime type match found, be happy and return
- end
- end
- end
-
- if @order.include?(Mime::ALL)
- @responses[Mime::ALL].call
- else
- @controller.send :head, :not_acceptable
- end
+ def generate_method_for_mime(mime)
+ sym = mime.is_a?(Symbol) ? mime : mime.to_sym
+ const = sym.to_s.upcase
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ def #{sym}(&block) # def html(&block)
+ custom(Mime::#{const}, &block) # custom(Mime::HTML, &block)
+ end # end
+ RUBY
end
+
end
end
end
View
6 actionpack/test/controller/mime_responds_test.rb
@@ -436,9 +436,9 @@ def test_extension_synonyms
def test_render_action_for_html
@controller.instance_eval do
def render(*args)
- unless args.empty?
- @action = args.first[:action] || action_name
- end
+ @action = args.first[:action] unless args.empty?
+ @action ||= action_name
+
response.body = "#{@action} - #{@template.formats}"
end
end

0 comments on commit 3f445b3

Please sign in to comment.
Something went wrong with that request. Please try again.