Railsで静的なページを動的にしたくない話
http://terut.github.io/staticman/
staticmanというlayoutやviewを再利用して、静的ページを吐き出すgemを書いた。
Railsで使うことを想定してる。
使い方
設定ファイルをgenerateして、設定ファイルを書き換える。
$ bundle exec rails g staticman:config
create config/staticman.rb
$ vim config/staticman.rb
設定ファイルは、静的ページのlayoutとviewを設定しておく。
# config/staticman.rb Staticman.configure do |config| config.static_pages = [ { file: 'statics/about', layout: 'application' }, { file: 'statics/404', layout: 'application' } ] # config.static_dir = 'public' config.host = 'staticman.github.com' # config.controller_context_class = nil end
あとは設定した静的ページのviewを編集して、準備ができたら出力する。
$ bundle exec rake staticman:build create public/about.html create public/404.html
Railsでのviewとなんら変わりなく書けるし、テンプレートエンジンもそのまま使える。
仕組み
RailsのApplicationControllerを継承したProxyのControllerとRequestを用意して、あとはRailsのレンダリングの機構にまかせてる。
実に単純で、ちょっと泥臭いけど、ActionViewのみでレンダリングしようと思ったらControllerのhelper_methodの仕組みがControllerインスタンスにdelegateしてるので、なかなか辛いことが分かり、こうなってる。
もし、viewの中でメソッドが見つからない場合は、ActionView::Baseを継承した無名クラスにmethod_missingを持ったモジュールをincludeしてあるので、メソッド見つからなかったよってWarningだして、nilを返してレンダリングを続ける。
あくまで開発時にのみ使うツールかなと思ったので、本体のクラスに影響がないようにしたつもり。
継承せずに特異メソッドを使ってもよいのかもしれないけど、とりあえずこうした。
問題点
現状、2つプロジェクトに導入してみて、一応うまく動いてる。
けど、以下の点がめんどくさいなと思った。
- Rails.envをproductionで吐きたい(むしろassetsのdigest考えるとそっちのほうが多い気がする)場合、別途envを用意しなきゃいけなくね?
- URL helperの*_urlを解決するためにhostを設定として用意するのが微妙にDRYじゃない
このブログを見て、ナルホディウスですぞと思ったそこのあなた、Pull Requestお待ちしてます。
静的ページの管理の問題
以前から、Railsとかにおける静的なページ、いわゆるsorry.htmlだとか、404.htmlとかをどうやって管理したらいいんだぜ?と思ってた。
まず最初に思いつくのが、ユー動的にしちゃいなよということ。
high_voltageとかはRailsにマウントするタイプなので、動的にページをレンダリングしてるように見えて、Railsに組み込む方針をとってるっぽい。
動的な要素(例えばセッション状態を見てログインユーザを表示したいとか)がある場合、layoutやviewを使い回せて、とても有益。
ただ現状関わっているいくつかのプロジェクトに関して、そんな要件はないので、静的なページは個人的にRailsのレイヤより前のWebサーバからresponseを返したいなと思った。
んで、動的に作らない場合、問題になってくるのが修正漏れ(少なくとも僕の職場では何回かあった)で、静的なページを配信する残念リリースをする。
静的なページで同じようなマークアップがすべてのファイルにあったりして、テストとかも書いてないので、目grep力たった5か、ゴミめという僕にとって気づくのは難しい。
ということで、動的に静的なページを生成すればlayoutとviewを使い回せて幸せになれるんやで工藤!というところに行き着いた。
それがhigh_voltageで出来るならそっちを使ったほうがいいし、別にもっとよいライブラリがあればそれを使いましょう。
ついでに気が向いたら@terutにリプライで教えてください。
思ったこと
実際にRailsがどうやってレンダリングしてんだろーなと思って色々と潜ってみたけど、勉強になった反面、僕には才能なんてなかった。
もっといい方法があれば、ぜひ教えてほしいし、この方法が良さそうなら、どんどんよくしてもっと楽したい。
自分のライブラリに自分でissueを書くのはとても趣があり、いいんだけど、僕の英語がクソすぎて何言ってんのか分からなくなった。
最後にstaticmanというのはstaticおじさんということであり、静的なページを書き続けてくれるおじさんの意である。
使い方はREADMEに一通り書いておいたつもりなので、興味あれば読むといいと思う。