diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index a1e94384bd..bcbd3d1387 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add support for conditional values to TagBuilder. + + *Joel Hawksley* + * Fix `select_tag` so that it doesn't change `options` when `include_blank` is present. *Younes SERRAJ* diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index 3979721d34..123da36c3f 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -85,7 +85,9 @@ module ActionView end def tag_option(key, value, escape) - if value.is_a?(Array) + case value + when Array, Hash + value = build_tag_values(value) value = escape ? safe_join(value, " ") : value.join(" ") else value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s.dup @@ -95,6 +97,26 @@ module ActionView end private + + def build_tag_values(*args) + tag_values = [] + + args.each do |tag_value| + case tag_value + when String + tag_values << tag_value if tag_value.present? + when Hash + tag_value.each do |key, val| + tag_values << key if val + end + when Array + tag_values << build_tag_values(*tag_value).presence + end + end + + tag_values.compact.flatten + end + def prefix_tag_option(prefix, key, value, escape) key = "#{prefix}-#{key.to_s.dasherize}" unless value.is_a?(String) || value.is_a?(Symbol) || value.is_a?(BigDecimal) @@ -233,6 +255,9 @@ module ActionView # # tag("div", data: { name: 'Stephen', city_state: %w(Chicago IL) }) # # =>
+ # + # tag("div", class: { highlight: current_user.admin? }) + # # =>
def tag(name = nil, options = nil, open = false, escape = true) if name.nil? tag_builder @@ -260,6 +285,8 @@ module ActionView # # =>

Hello world!

# content_tag(:div, "Hello world!", class: ["strong", "highlight"]) # # =>
Hello world!
+ # content_tag(:div, "Hello world!", class: ["strong", { highlight: current_user.admin? }]) + # # =>
Hello world!
# content_tag("select", options, multiple: true) # # => # diff --git a/actionview/test/template/tag_helper_test.rb b/actionview/test/template/tag_helper_test.rb index 9a6226fd04..1dc27fe20c 100644 --- a/actionview/test/template/tag_helper_test.rb +++ b/actionview/test/template/tag_helper_test.rb @@ -239,6 +239,68 @@ class TagHelperTest < ActionView::TestCase assert_equal '

limelight

', str end + def test_content_tag_with_conditional_hash_classes + str = content_tag("p", "limelight", class: { "song": true, "play": false }) + assert_equal "

limelight

", str + + str = content_tag("p", "limelight", class: [{ "song": true }, { "play": false }]) + assert_equal "

limelight

", str + + str = content_tag("p", "limelight", class: { song: true, play: false }) + assert_equal "

limelight

", str + + str = content_tag("p", "limelight", class: [{ song: true}, nil, false]) + assert_equal "

limelight

", str + + str = content_tag("p", "limelight", class: ["song", { foo: false}]) + assert_equal "

limelight

", str + + str = content_tag("p", "limelight", class: { "song": true, "play": true }) + assert_equal "

limelight

", str + + str = content_tag("p", "limelight", class: { "song": false, "play": false }) + assert_equal '

limelight

', str + end + + def test_tag_builder_with_conditional_hash_classes + str = tag.p "limelight", class: { "song": true, "play": false } + assert_equal "

limelight

", str + + str = tag.p "limelight", class: [{ "song": true }, { "play": false }] + assert_equal "

limelight

", str + + str = tag.p "limelight", class: { song: true, play: false } + assert_equal "

limelight

", str + + str = tag.p "limelight", class: [{ song: true}, nil, false] + assert_equal "

limelight

", str + + str = tag.p "limelight", class: ["song", { foo: false}] + assert_equal "

limelight

", str + + str = tag.p "limelight", class: { "song": true, "play": true } + assert_equal "

limelight

", str + + str = tag.p "limelight", class: { "song": false, "play": false } + assert_equal '

limelight

', str + end + + def test_content_tag_with_unescaped_conditional_hash_classes + str = content_tag("p", "limelight", { class: { "song": true, "play>": true } }, false) + assert_equal "

\">limelight

", str + + str = content_tag("p", "limelight", { class: ["song", { "play>": true }] }, false) + assert_equal "

\">limelight

", str + end + + def test_tag_builder_with_unescaped_conditional_hash_classes + str = tag.p "limelight", class: { "song": true, "play>": true }, escape_attributes: false + assert_equal "

\">limelight

", str + + str = tag.p "limelight", class: ["song", { "play>": true }], escape_attributes: false + assert_equal "

\">limelight

", str + end + def test_content_tag_with_data_attributes assert_dom_equal '

limelight

', content_tag("p", "limelight", data: { number: 1, string: "hello", string_with_quotes: 'double"quote"party"' })