From a288cc1e011cf25508d1b56f393023bb40ab441e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Strza=C5=82kowski?= Date: Tue, 24 Dec 2013 16:53:10 +0100 Subject: Add any/all support for variants Like `format.any`, you can do the same with variants. It works for both inline: respond_to do |format| format.html.any { render text: "any" } format.html.phone { render text: "phone" } end and block syntax: respond_to do |format| format.html do |variant| variant.any(:tablet, :phablet){ render text: "any" } variant.phone { render text: "phone" } end end --- .../lib/action_controller/metal/mime_responds.rb | 81 ++++++++++++++-------- 1 file changed, 54 insertions(+), 27 deletions(-) (limited to 'actionpack/lib/action_controller/metal/mime_responds.rb') diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index fbc4024c2d..d5e08b7034 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -217,6 +217,24 @@ module ActionController #:nodoc: # format.html.phone { redirect_to progress_path } # format.html.none { render "trash" } # end + # + # Variants also support common `any`/`all` block that formats have. + # + # It works for both inline: + # + # respond_to do |format| + # format.html.any { render text: "any" } + # format.html.phone { render text: "phone" } + # end + # + # and block syntax: + # + # respond_to do |format| + # format.html do |variant| + # variant.any(:tablet, :phablet){ render text: "any" } + # variant.phone { render text: "phone" } + # end + # end # # Be sure to check the documentation of +respond_with+ and # ActionController::MimeResponds.respond_to for more examples. @@ -224,7 +242,7 @@ module ActionController #:nodoc: raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given? if collector = retrieve_collector_from_mimes(mimes, &block) - response = collector.response(request.variant) + response = collector.response response ? response.call : render({}) end end @@ -366,7 +384,7 @@ module ActionController #:nodoc: if collector = retrieve_collector_from_mimes(&block) options = resources.size == 1 ? {} : resources.extract_options! options = options.clone - options[:default_response] = collector.response(request.variant) + options[:default_response] = collector.response (options.delete(:responder) || self.class.responder).call(self, resources, options) end end @@ -399,7 +417,7 @@ module ActionController #:nodoc: # is available. def retrieve_collector_from_mimes(mimes=nil, &block) #:nodoc: mimes ||= collect_mimes_from_class_level - collector = Collector.new(mimes) + collector = Collector.new(mimes, request.variant) block.call(collector) if block_given? format = collector.negotiate_format(request) @@ -437,8 +455,9 @@ module ActionController #:nodoc: include AbstractController::Collector attr_accessor :format - def initialize(mimes) + def initialize(mimes, variant = nil) @responses = {} + @variant = variant mimes.each { |mime| @responses["Mime::#{mime.upcase}".constantize] = nil } end @@ -457,18 +476,20 @@ module ActionController #:nodoc: @responses[mime_type] ||= if block_given? block else - VariantCollector.new + VariantCollector.new(@variant) end end - def response(variant) + def response response = @responses.fetch(format, @responses[Mime::ALL]) - if response.is_a?(VariantCollector) - response.variant(variant) - elsif response.nil? || response.arity == 0 + if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax + response.variant + elsif response.nil? || response.arity == 0 # `format.html` - just a format, call its block response - else - lambda { response.call VariantFilter.new(variant) } + else # `format.html{ |variant| variant.phone }` - variant block syntax + variant_collector = VariantCollector.new(@variant) + response.call(variant_collector) #call format block with variants collector + variant_collector.variant end end @@ -476,31 +497,37 @@ module ActionController #:nodoc: @format = request.negotiate_mime(@responses.keys) end - #Used for inline syntax class VariantCollector #:nodoc: - def initialize + def initialize(variant = nil) + @variant = variant @variants = {} end - def method_missing(name, *args, &block) - @variants[name] = block if block_given? - end - - def variant(name) - @variants[name.nil? ? :none : name] + def any(*args, &block) + if block_given? + if args.any? && args.none?{ |a| a == @variant } + args.each{ |v| @variants[v] = block } + else + @variants[:any] = block + end + end end - end + alias :all :any - #Used for nested block syntax - class VariantFilter #:nodoc: - def initialize(variant) - @variant = variant + def method_missing(name, *args, &block) + @variants[name] = block if block_given? end - def method_missing(name) - if block_given? - yield if name == @variant || (name == :none && @variant.nil?) + def variant + key = if @variant.nil? + :none + elsif @variants.has_key?(@variant) + @variant + else + :any end + + @variants[key] end end end -- cgit v1.2.3