[ActionView] A helper to conditionally add classes

Hi,

After doing some React and inspired by https://github.com/JedWatson/classnames, what do you think about adding a helper method to conditionally join classes.

For example, we have this code in our app to conditionally add classes to a div:

project.status.active?, 'owner' => project.owner == current_user)">

content_tag(:div, class: class_names(“project”, “active” => project.status.active?, “owner” => project.owner == current_user))

Do you think is worth it to put it into Rails?

Thanks!

Your code will be cleaner if you pass the classes in as an array. <%= content_tag :div, content, class: [‘a’, ‘b’, nil, ‘c’] %>; the nil elements will be ignored. Doing that, you can create the array elsewhere in your code however you want and then pass it in.

I remembered reading a post about that: A Cleaner Way To Set Multiple Conditional CSS Classes for ‘link_to’.

It mentions there’s already a gem that does that called css-class-string and the do it yourself implementation is really simple as a helper.

Here is what I use. It is also based on classNames from JavaScriptland. I might remove the .join() now that I know you can pass a string array to class. Thanks Andrew.

def class_names(*classes)
  class_array = [(classes.shift if classes.first.is_a? String), classes.first.select { |_, v| v }.keys]
  class_array.compact.join(" ")
end

<% content_tag(:div, class: class_names('btn', 'btn-danger': false, 'btn-success': true, btn_other: true)) %>

I have had similar thoughts. I wrote a generic view helper a while back that I bring into all of my applications:

Clean-stringify an arbitrary collection of args.

Useful for building the class attribute values.

def meld(*args)

args.flatten

  .compact

  .map(&:to_s)

  .map(&:strip)

  .uniq

  .join(' ')

end

I find this a powerful helper for building the class attribute. I even wrote up a small post on the kinds of use-cases and edge-cases it solves for: http://fractaledmind.com/articles/a-function-for-generating-html-attribute-values/