Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Inline variants syntax

In most cases, when setting variant specific code, you're not sharing any code
within format.

Inline syntax can vastly simplify defining variants in those situations:

  respond_to do |format|
    format.js { render "trash" }
    format.html do |variant|
      variant.phone { redirect_to progress_path }
      variant.none  { render "trash" }
    end
  end

Becomes:

  respond_to do |format|
    format.js         { render "trash" }
    format.html.phone { redirect_to progress_path }
    format.html.none  { render "trash" }
  end
  • Loading branch information...
commit edacdbfaf93ac1a81ec8654da4df03b80488e85c 1 parent fbb6be5
@strzalek strzalek authored
View
26 actionpack/lib/action_controller/metal/mime_responds.rb
@@ -445,12 +445,18 @@ def any(*args, &block)
def custom(mime_type, &block)
mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
- @responses[mime_type] ||= block
+ @responses[mime_type] ||= if block_given?
+ block
+ else
+ VariantCollector.new
+ end
end
def response(variant)
response = @responses.fetch(format, @responses[Mime::ALL])
- if response.nil? || response.arity == 0
+ if response.is_a?(VariantCollector)
+ response.variant(variant)
+ elsif response.nil? || response.arity == 0
response
else
lambda { response.call VariantFilter.new(variant) }
@@ -461,6 +467,22 @@ def negotiate_format(request)
@format = request.negotiate_mime(@responses.keys)
end
+ #Used for inline syntax
+ class VariantCollector #:nodoc:
+ def initialize
+ @variants = {}
+ end
+
+ def method_missing(name, *args, &block)
+ @variants[name] = block if block_given?
+ end
+
+ def variant(name)
+ @variants[name.nil? ? :none : name]
+ end
+ end
+
+ #Used for nested block syntax
class VariantFilter #:nodoc:
def initialize(variant)
@variant = variant
View
39 actionpack/test/controller/mime/respond_to_test.rb
@@ -175,6 +175,22 @@ def variant_plus_none_for_format
end
end
+ def variant_inline_syntax
+ respond_to do |format|
+ format.js { render text: "js" }
+ format.html.none { render text: "none" }
+ format.html.phone { render text: "phone" }
+ end
+ end
+
+ def variant_inline_syntax_without_block
+ respond_to do |format|
+ format.js
+ format.html.none
+ format.html.phone
+ end
+ end
+
protected
def set_layout
case action_name
@@ -554,10 +570,31 @@ def test_multiple_variants_for_format
assert_equal "tablet", @response.body
end
-
def test_no_variant_in_variant_setup
get :variant_plus_none_for_format
assert_equal "text/html", @response.content_type
assert_equal "none", @response.body
end
+
+ def test_variant_inline_syntax
+ get :variant_inline_syntax, format: :js
+ assert_equal "text/javascript", @response.content_type
+ assert_equal "js", @response.body
+
+ get :variant_inline_syntax
+ assert_equal "text/html", @response.content_type
+ assert_equal "none", @response.body
+
+ @request.variant = :phone
+ get :variant_inline_syntax
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+ end
+
+ def test_variant_inline_syntax_without_block
+ @request.variant = :phone
+ get :variant_inline_syntax_without_block
+ assert_equal "text/html", @response.content_type
+ assert_equal "phone", @response.body
+ end
end
View
1  actionpack/test/fixtures/respond_to/variant_inline_syntax_without_block.html+phone.erb
@@ -0,0 +1 @@
+phone
Please sign in to comment.
Something went wrong with that request. Please try again.