解せぬ日記

雑な話をする

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に一通り書いておいたつもりなので、興味あれば読むといいと思う。