LoginSignup
5
1

More than 5 years have passed since last update.

Rails の view で classnames みたいなことをする

Last updated at Posted at 2018-05-30

背景: classnames とは

HTML を書いていると、条件に応じて class 属性の値を変えたくなることがしばしばあります。

例えばある span 要素に baz のときだけ "bar" をつけたいとします。 slim で愚直に書くとたとえばこんな感じになります:

span[class="foo #{'bar' if baz}"]

条件が一つくらいならまだいいのですが、これが増えてくるとだんだんどういうときにどういう class になるのかわかりにくくなってきます。(しかも上のコードには実はバグがあります)

この問題を解決するのに JavaScript 界隈ではよく classnames という npm パッケージが使われます:

const classNames = require("classnames")

classNames("foo", { bar: true })  //=> "foo bar"
classNames("foo", { bar: false }) //=> "foo"

Rails で classnames 相当のものを実装する

Ruby も探してみると一応 classnames という gem があるのですが、広く使われているわけではなかったり、最終コミットから 2 年近く経過していたりであまり使いたくないと思う人もいるかも知れません。

幸いにして ActiveSupport が有効な環境では classnames のサブセットを実装することは非常に簡単です。

module ApplicationHelper
  # Create conditional css classes. Based on github.com/JedWatson/classnames
  #
  # @example
  #   classnames('foo', bar: true, baz: false)
  #   #=> 'foo bar'
  def classnames(*args)
    options = args.extract_options!
    (args + options.select { |_, v| v }.keys).join(' ')
  end
end

途中で使っている .extract_options! は ActiveSupport によって Array に追加されるメソッドです。これを使うと冒頭の spam 要素の例は

span[class=classnames('foo', bar: baz)]

のように書き直すことができます。

Ref

5
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1