RailsでTwitter Bootstrapを使う
Twitter BootstarpをRailsで使う場合、Twitter Bootstrap for Rails 3.1 Asset Pipelineというgemが便利。
便利なのだけど、CSSやHTMLの生成に使うテンプレート言語のデフォルトが好みじゃない場合にはどうするのがいいのだろうか。具体的にはERB、LESSという組み合わせじゃなくて、HAML、SCSSにしたい。
ちょっと検索すると、SASS化したり、HAML化されたTwitter Bootstrapはある。ということは混ぜて使えばオッケーなのか。
RailsのGeneratorって、そういえばどう実現されてるのかと思って、Rails::Generatorsあたりを眺めてみた。何となくコード生成って黒魔術っぽく感じていたけど、基本的にファイルに文字列をinterpolateしつつコピーしたりしているだけということが分かった。
RailsのGeneratorで使われてるThorっていうのは、何だっけと思って調べたら、Yehuda Katzが2008年にリリースしたRakeに代わるスクリプティングサポートライブラリだった。RakeとSakeとかRubyのスクリプティング環境って実はイマイチじゃね?フルスタックのスクリプティングライブラリがほしいよね。ということで、Thorを作ったよとYehudaはブログで言っている。それを眺めたJose Valimが、これってRailsのGeneratorに使えるんじゃね? copy_fileとかさえ実装すればさ。ということで、Google Summer of CodeのプロジェクトとしてRails3に向けて実装したもののようだ(ブログ)。
Twitter Bootstrapのgeneratorは、こんな感じ。
module Bootstrap module Generators class InstallGenerator < Rails::Generators::Base source_root File.expand_path("../templates", __FILE__) desc "This generator installs Twitter Bootstrap to Asset Pipeline" def add_assets if File.exist?('app/assets/javascripts/application.js') insert_into_file "app/assets/javascripts/application.js", "//= require twitter/bootstrap\n", :after => "jquery_ujs\n" else copy_file "application.js", "app/assets/javascripts/application.js" end if File.exist?('app/assets/stylesheets/application.css') insert_into_file "app/assets/stylesheets/application.css", " *= require twitter/bootstrap\n", :after => "require_self\n" else copy_file "application.css", "app/assets/stylesheets/application.css" end end
Rails::Generators::Baseは、Thor::Groupを継承している。Thor::Groupは、メソッド定義の順に従って、まとめてタスク(=メソッド)を実行するクラス。insert_into_fileとかで、「ここに1行記述を追記してちょ」というようなことができるらしい。なるほど。
RailsのGeneratorって、こう、いろいろとgemに付属してきて便利なんだけど、結局のところテンプレートファイルを展開するだけだから、ほかのGeneratorと組み合わせると上手くいかないことが多いように思う。この辺を組み合わせ自由にしてDRYな仕組みができれば素晴らしそうだけど、原理的に難しそう。生成したコードを後からerb2hamlとかhtml2hamlとかで変換するのが正解っぽい。
やれるとしたら、Twitter Bootstrap for Rails 3.1 Asset PipelineにHAMLのファイルをジャカジャカ突っ込んでオプションで切り替えられるようにすることだろうか。gemfileにhaml-railsが書いてあれば、自動判別でERBではなくHAMLを生成するとか。