はじめに: 404.htmlや500.htmlといったエラーページをhtmlで直接書くのって面倒じゃないですか?
Railsでは独自デザインの404ページや500ページをpublic/404.html
やpublic/500.html
に置くことができます。
ただし、このファイルは静的なファイルなので、HTMLやCSSも静的にしなければなりません。
そのためデザインをサイト全体で合わせようとして、以下のようにHTML内にがんばって静的なCSSを埋め込んだりしているケースもあるのではないでしょうか?
public/404.html
<html>
<head>
<style type="text/css">
// コンパイル済みのapplication.cssからコピペした自前のCSSが何百行も並んだり
// ...
// ...
// ...
</style>
<!-- もしくはpublic以下に専用のcssファイルを用意したり -->
<link rel="stylesheet" media="all" href="/css/errors.css" />
</head>
<body>
<h1>404 Not found</h1>
<p>ページが見つかりません。</p>
</body>
</html>
この問題を解決するために、hanmotoというgemを作りました。
このgemは弊社ソニックガーデンの複数のプロジェクトで1年以上、本番利用されてきた実績があります。
今回の記事ではこのgemの概要と使い方を紹介します。
何が出来るの?
- hamlやslimを使って静的ページが書ける
- WebpackerやSprocketsで生成したcssをそのまま使える
- Layoutファイルを使ってエラーページをDRYに管理できる
- link_to等のヘルパーが使える
- public以下にファイルが吐き出されるので、railsが死んでも表示出来る
インストール
Gemfile
gem 'hanmoto'
$ bundle install
使い方
404.htmlの例
レイアウトを用意
app/views/layouts/public.html.haml
!!!
%html
%head
%title #{yield(:title)} | MyAPP
= stylesheet_pack_tag 'application', media: 'all'
= favicon_link_tag '/favicon.ico'
%body
= yield
ビューを用意
app/views/public_pages/404.html.haml
- provide(:title, 'Not found')
%h1 Not found
%p This webpage is not found.
%p= link_to 'Home', root_path
public以下にファイルを生成
$ rake assets:precompile
OR
$ rake hanmoto:publish
.gitignore
にpublic/404.html
を追加しておいて、デプロイ時にrake assets:precompile
またはrake hanmoto:publish
を実行するという使い方を想定しています。
出力結果
public/404.html
<!DOCTYPE html>
<html>
<head>
<title>Not found | MyAPP</title>
<link rel="stylesheet" media="all" href="/packs/css/application-cc5b8b21.css" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body>
<h1>Not found</h1>
<p>This webpage is not found.</p>
<p><a href="/">Home</a></p>
</body>
</html>
htmlファイル以外の例
robots.txtを動的に生成する場合
app/views/public_pages/robots.text.erb
<% unless Rails.env.production? %>
User-Agent: *
Disallow: /
<% end %>
設定
config/initializers/hanmoto.rb
Hanmoto.configure do |config|
# ビューファイルを置くディレクトリを変更したい場合は指定してください
# config.view_dir = 'public_page'
# レイアウトファイルを変更したい場合はファイルタイプ別に指定してください
# config.layouts = {
# html: 'public',
# }
end
その他
仕組み
-
ApplicationController.renderer
のレンダリング結果をpublic
以下に書き出しています。 - 参考: [Rails 5] コントローラの制約を受けずに任意のビューテンプレートをレンダリングする
Herokuでも使える?
RailsアプリをHerokuにデプロイすると自動的にrake assets:precompile
が実行されるので、特に意識する必要なく利用できます。
gemの名前の由来
publicに書き出す -> publisher -> 版元
リポジトリ