From 7af12d04cebe3a1ffcf55cae967d22fc7b0606c8 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 12 Mar 2006 06:02:44 +0000 Subject: [PATCH] Added synonym and custom type handling to respond_to [DHH] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3844 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../lib/action_controller/mime_responds.rb | 32 ++++++----- actionpack/lib/action_controller/mime_type.rb | 56 ++++++++++--------- actionpack/lib/action_controller/request.rb | 4 +- .../test/controller/mime_responds_test.rb | 28 ++++++++++ 4 files changed, 79 insertions(+), 41 deletions(-) diff --git a/actionpack/lib/action_controller/mime_responds.rb b/actionpack/lib/action_controller/mime_responds.rb index e8d1ba089b..44b9dd933c 100644 --- a/actionpack/lib/action_controller/mime_responds.rb +++ b/actionpack/lib/action_controller/mime_responds.rb @@ -26,22 +26,28 @@ def initialize(block_binding) @order = [] @responses = {} end + + def custom(mime_type, *args, &block) + mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s) + + @order << mime_type + + if block_given? + @responses[mime_type] = block + else + if argument = args.first + eval("__mime_responder_arg__ = " + (argument.is_a?(String) ? "'" + argument + "'" : argument), @block_binding) + @responses[mime_type] = eval(DEFAULT_BLOCKS[(mime_type.to_sym.to_s + "_arg").to_sym], @block_binding) + else + @responses[mime_type] = eval(DEFAULT_BLOCKS[mime_type.to_sym], @block_binding) + end + end + end for mime_type in %w( all html js xml rss atom yaml ) eval <<-EOT def #{mime_type}(argument = nil, &block) - @order << Mime::#{mime_type.upcase} - - if block_given? - @responses[Mime::#{mime_type.upcase}] = block - else - if argument - eval("__mime_responder_arg__ = " + (argument.is_a?(String) ? "'" + argument + "'" : argument), @block_binding) - @responses[Mime::#{mime_type.upcase}] = eval(DEFAULT_BLOCKS[(Mime::#{mime_type.upcase}.to_sym.to_s + "_arg").to_sym], @block_binding) - else - @responses[Mime::#{mime_type.upcase}] = eval(DEFAULT_BLOCKS[Mime::#{mime_type.upcase}.to_sym], @block_binding) - end - end + custom(Mime::#{mime_type.upcase}, argument, &block) end EOT end @@ -52,7 +58,7 @@ def respond @responses[@order.first].call return else - if @order.include?(priority) + if priority === @order @responses[priority].call return # mime type match found, be happy and return end diff --git a/actionpack/lib/action_controller/mime_type.rb b/actionpack/lib/action_controller/mime_type.rb index 15dbc70915..ad2f5aaac5 100644 --- a/actionpack/lib/action_controller/mime_type.rb +++ b/actionpack/lib/action_controller/mime_type.rb @@ -1,44 +1,48 @@ module Mime class Type < String - def initialize(string, part_of_all = true) - @part_of_all = part_of_all + def self.lookup(string) + LOOKUP[string] + end + + def initialize(string, symbol = nil, synonyms = []) + @symbol, @synonyms = symbol, synonyms super(string) end def to_sym - SYMBOLIZED_MIME_TYPES[self] ? SYMBOLIZED_MIME_TYPES[self] : to_sym + @symbol || to_sym end def ===(list) if list.is_a?(Array) - list.include?(self) + (@synonyms + [ self ]).any? { |synonym| list.include?(synonym) } else super end end end - SYMBOLIZED_MIME_TYPES = { - "" => :unspecified, - "*/*" => :all, - "text/html" => :html, - "application/javascript" => :js, - "application/x-javascript" => :js, - "text/javascript" => :js, - "text/xml" => :xml, - "application/xml" => :xml, - "application/rss+xml" => :rss, - "application/rss+atom" => :atom, - "application/x-xml" => :xml, - "application/x-yaml" => :yaml - } + ALL = Type.new "*/*", :all + HTML = Type.new "text/html", :html + JS = Type.new "text/javascript", :js, %w( application/javascript application/x-javascript ) + XML = Type.new "text/xml", :xml, %w( application/xml application/x-xml ) + RSS = Type.new "application/rss+xml", :rss + ATOM = Type.new "application/atom+xml", :atom + YAML = Type.new "application/x-yaml", :yaml + + LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) } + + LOOKUP["*/*"] = ALL + LOOKUP["text/html"] = HTML + LOOKUP["application/rss+xml"] = RSS + LOOKUP["application/atom+xml"] = ATOM + LOOKUP["application/x-yaml"] = YAML + + LOOKUP["text/javascript"] = JS + LOOKUP["application/javascript"] = JS + LOOKUP["application/x-javascript"] = JS - ALL = Type.new "*/*" - HTML = Type.new "text/html" - JS = Type.new "text/javascript" - JAVASCRIPT = Type.new "text/javascript" - XML = Type.new "application/xml" - RSS = Type.new "application/rss+xml" - ATOM = Type.new "application/atom+xml" - YAML = Type.new "application/x-yaml" + LOOKUP["text/xml"] = XML + LOOKUP["application/xml"] = XML + LOOKUP["application/x-xml"] = XML end \ No newline at end of file diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 300a0ea60c..cbefc2e490 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -61,7 +61,7 @@ def content_type end end - @content_type = Mime::Type.new(@content_type) + @content_type = Mime::Type.lookup(@content_type) end def accepts @@ -71,7 +71,7 @@ def accepts [ content_type, Mime::ALL ] else @env['HTTP_ACCEPT'].split(";").collect! do |mime_type| - Mime::Type.new(mime_type.strip) + Mime::Type.lookup(mime_type.strip) end end end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 184110aad1..1470fa9899 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -56,6 +56,14 @@ def made_for_content_type end end + def custom_type_handling + respond_to do |type| + type.html { render :text => "HTML" } + type.custom("application/crazy-xml") { render :text => "Crazy XML" } + type.all { render :text => "Nothing" } + end + end + def rescue_action(e) raise unless ActionController::MissingTemplate === e end @@ -155,4 +163,24 @@ def test_with_content_type get :made_for_content_type assert_equal "RSS", @response.body end + + def test_synonyms + @request.env["HTTP_ACCEPT"] = "application/javascript" + get :js_or_html + assert_equal 'JS', @response.body + + @request.env["HTTP_ACCEPT"] = "application/x-xml" + get :using_argument_defaults + assert_equal "\n\n David\n\n", @response.body + end + + def test_custom_types + @request.env["HTTP_ACCEPT"] = "application/crazy-xml" + get :custom_type_handling + assert_equal 'Crazy XML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/html" + get :custom_type_handling + assert_equal 'HTML', @response.body + end end \ No newline at end of file -- GitLab