いい感じのAction View用gemを作ったら、すでに提供されている機能だった
解決したかった問題
ActionViewで、条件付きで有効になるクラスを作ろうとすると、ややこしくなることがある。
buttonは常につけて、特定のコントローラーで処理しているときだけbutton-activeをつけたいとき、erbで頑張ると下記のようになる。
<a class="button<%= " button-active" if controller_name=="targets" %>"> # controller_name == "targets" => "button button-active" # controller_name != "targets" => "button"
この方法だと、ちょっと嫌な点がある
- 複数の条件付きクラスがあると読み解きにくくなる
- クラス名とクラス名の間のスペースをつけ忘れてはいけないので、メンテ時にうっかり消さないように注意が必要
作った
これをもう少し単純に書けないかと思ってgemを作った。
<a class="<%= html_class(:button, "button-active": -> { if controller_name=="targets" }) %>"> # controller_name == "targets" => "button button-active" # controller_name != "targets" => "button"
スペースのことを気にしなくて良くなった。 複数の条件付きクラスがあっても、配列の表現に従った統一された記述ができるので読みやすい。 セマンティクス的にもわかりやすい。
あった
なんかいい感じなインターフェースが作れたなと思ってかなり満足感あったので、社内で宣伝した。
ソッコーで「それrailsにありませんでしたっけ」と教えてもらった。
rails6.1から、class_names
という名前のヘルパーメソッドが使えるようになっていた。
<a class="<%= class_names('button', { 'button-active': controller_name=="targets" }) %>">
下記のような細かい違いはあるものの、受けられる恩恵はだいたい同じ。
- html_classは条件付きクラスはキーワード引数として渡す。class_namesはハッシュとして渡す。
- html_classは条件を表すProcを受け取る。class_namesはブール値を受け取る。
さらに
class_namesで利用できる条件付きクラスの仕様は、ActionViewのtag
メソッドでも利用できる。
つまり、link_to
などのrailsでclassを渡せるメソッドでは下記のように書ける。
<% link_to class=['button', { 'button-active': controller_name=="targets" }] %>
ActionView::Helpers::TagHelper
ちゃんとサンプルにも記載がある。
まじかよぉ(すごい)
なぜ作ってしまったのか
- テンプレート側で頑張るコードを仕事でたくさん見かけたので、そういうもんなんだという先入観から入った
- それでも半年くらい前にこういう機能無いかなって調べたけど、そのときは見つけられなかったので、無いもんだと思ってた(その時すでにあったはずだけど見つけられていなかった)
- アイディアを思いついたときにうわ俺天才じゃんってなって勢いで作ったので、再度類似のものが無いか調べなかった
- コードの量が少なく、簡単に実現できたので、まあカブってもそんな痛手じゃないやって思った。
得られたもの
世の中的には意味のないことをしてしまったのだけれど、個人としてはいろいろ得るものがあった。
- 人にgemを自慢すると、関連情報を教えてもらえることがわかった
- class_namesの実装のなかで、書いた人に共感しつつ、何を捨てて何を得ようとしたのかわかった
- 解決しようとしていた問題は同じなので、割とセンスあるかもしれないなって思えた
- 解決方法はclass_namesのほうがスマートだったので、自分よりすごい人のテクを深く味わえた
今後どうする
自分は結構得られたものが多くて嬉しかったのだけれど、使ってしまった人には迷惑を書けてしまうと思う。 ということで今後は下記をやる。
- READMEにclass_namesをつかってねと書く。
- gemを作るときは競合がないか調べる。
- でも調べても見つからないこともあるので、そのときはごめんなさい
- 開発途中のものをみてもらえるように、ミートアップや勉強会に顔を出すなど…
と思いつつ、カブったときのリスクが小さいときは、やっぱり書いちゃうかなと思った。