提交 f2dfa83f 编写于 作者: D David Heinemeier Hansson

Merge pull request #14043 from strzalek/variants-negotiation

Variant negotiation
......@@ -236,6 +236,18 @@ def clear_respond_to
# end
# end
#
# You can also set an array of variants:
#
# request.variant = [:tablet, :phone]
#
# which will work similarly to formats and MIME types negotiation. If there will be no
# :tablet variant declared, :phone variant will be picked:
#
# respond_to do |format|
# format.html.none
# format.html.phone # this gets rendered
# end
#
# Be sure to check the documentation of +respond_with+ and
# <tt>ActionController::MimeResponds.respond_to</tt> for more examples.
def respond_to(*mimes, &block)
......@@ -488,7 +500,7 @@ def response
response
else # `format.html{ |variant| variant.phone }` - variant block syntax
variant_collector = VariantCollector.new(@variant)
response.call(variant_collector) #call format block with variants collector
response.call(variant_collector) # call format block with variants collector
variant_collector.variant
end
end
......@@ -519,15 +531,15 @@ def method_missing(name, *args, &block)
end
def variant
key = if @variant.nil?
:none
elsif @variants.has_key?(@variant)
@variant
if @variant.nil?
@variants[:none]
elsif (@variants.keys & @variant).any?
@variant.each do |v|
return @variants[v] if @variants.key?(v)
end
else
:any
@variants[:any]
end
@variants[key]
end
end
end
......
......@@ -68,10 +68,12 @@ def formats
# Sets the \variant for template.
def variant=(variant)
if variant.is_a? Symbol
if variant.is_a?(Symbol)
@variant = [variant]
elsif variant.is_a?(Array)
@variant = variant
else
raise ArgumentError, "request.variant must be set to a Symbol, not a #{variant.class}. " \
raise ArgumentError, "request.variant must be set to a Symbol or Array, not a #{variant.class}. " \
"For security reasons, never directly set the variant to a user-provided value, " \
"like params[:variant].to_sym. Check user-provided value against a whitelist first, " \
"then set the variant: request.variant = :tablet if params[:variant] == 'tablet'"
......
......@@ -740,4 +740,25 @@ def test_format_any_variant_any
assert_equal "text/javascript", @response.content_type
assert_equal "tablet", @response.body
end
def test_variant_negotiation_inline_syntax
@request.variant = [:tablet, :phone]
get :variant_inline_syntax_without_block
assert_equal "text/html", @response.content_type
assert_equal "phone", @response.body
end
def test_variant_negotiation_block_syntax
@request.variant = [:tablet, :phone]
get :variant_plus_none_for_format
assert_equal "text/html", @response.content_type
assert_equal "phone", @response.body
end
def test_variant_negotiation_without_block
@request.variant = [:tablet, :phone]
get :variant_inline_syntax_without_block
assert_equal "text/html", @response.content_type
assert_equal "phone", @response.body
end
end
......@@ -846,8 +846,12 @@ def url_for(options = {})
test "setting variant" do
request = stub_request
request.variant = :mobile
assert_equal :mobile, request.variant
assert_equal [:mobile], request.variant
request.variant = [:phone, :tablet]
assert_equal [:phone, :tablet], request.variant
end
test "setting variant with non symbol value" do
......
......@@ -94,7 +94,7 @@ def _render_template(options) #:nodoc:
variant = options[:variant]
lookup_context.rendered_format = nil if options[:formats]
lookup_context.variants = [variant] if variant
lookup_context.variants = variant if variant
view_renderer.render(view_context, options)
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册