diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index ffb364dce16684ea6fcadb8dff12195a64ebe4d3..b7f8661f2ecda6b5683ecb19c3372e7514af2fbd 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -94,7 +94,7 @@ def boolean_tag_option(key) def tag_option(key, value, escape) case value when Array, Hash - value = build_tag_values(value) if key.to_s == "class" + value = TagHelper.build_tag_values(value) if key.to_s == "class" value = escape ? safe_join(value, " ") : value.join(" ") else value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s @@ -104,25 +104,6 @@ def tag_option(key, value, escape) end private - def build_tag_values(*args) - tag_values = [] - - args.each do |tag_value| - case tag_value - when Hash - tag_value.each do |key, val| - tag_values << key if val - end - when Array - tag_values << build_tag_values(*tag_value).presence - else - tag_values << tag_value.to_s if tag_value.present? - 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) @@ -309,6 +290,19 @@ def content_tag(name, content_or_options_with_block = nil, options = nil, escape end end + # Returns a string of class names built from +args+. + # + # ==== Examples + # class_names("foo", "bar") + # # => "foo bar" + # class_names({ foo: true, bar: false }) + # # => "foo" + # class_names(nil, false, 123, "", "foo", { bar: true }) + # # => "foo bar" + def class_names(*args) + safe_join(build_tag_values(*args), " ") + end + # Returns a CDATA section with the given +content+. CDATA sections # are used to escape blocks of text containing characters which would # otherwise be recognized as markup. CDATA sections begin with the string @@ -339,6 +333,26 @@ def escape_once(html) end private + def build_tag_values(*args) + tag_values = [] + + args.each do |tag_value| + case tag_value + when Hash + tag_value.each do |key, val| + tag_values << key if val + end + when Array + tag_values << build_tag_values(*tag_value).presence + else + tag_values << tag_value.to_s if tag_value.present? + end + end + + tag_values.compact.flatten + end + module_function :build_tag_values + def tag_builder @tag_builder ||= TagBuilder.new(self) end diff --git a/actionview/test/template/tag_helper_test.rb b/actionview/test/template/tag_helper_test.rb index 44496bce9b56fd7b772b16c67c8b5a1bb9a98db5..2c800ff96cba8627c9cba46ae07facf462067942 100644 --- a/actionview/test/template/tag_helper_test.rb +++ b/actionview/test/template/tag_helper_test.rb @@ -338,6 +338,17 @@ def test_tag_builder_with_unescaped_conditional_hash_classes assert_equal "

\">limelight

", str end + def test_class_names + assert_equal "song play", class_names(["song", { "play": true }]) + assert_equal "song", class_names({ "song": true, "play": false }) + assert_equal "song", class_names([{ "song": true }, { "play": false }]) + assert_equal "song", class_names({ song: true, play: false }) + assert_equal "song", class_names([{ song: true }, nil, false]) + assert_equal "song", class_names(["song", { foo: false }]) + assert_equal "song play", class_names({ "song": true, "play": true }) + assert_equal "", class_names({ "song": false, "play": false }) + 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"' })