【動的VS静的】Railsの404/500エラーページ 静的の勝利

揉めに揉める議論

最初、もりじゅんさんの以下の記事を参考にさせていただこうとしたのですが、

morizyun.github.io

Qiitaでも(多分もりじゅんさんの記事を参考にした)同じ例をみかけて、そこでyuki24さんが、この方法はあまりよい方法でないというコメントをしてました。

Railsの404,500エラーページをカスタマイズ - Qiita

このコメントでひと記事できてしまうやつ。。笑

必読です。。

ということでApplicationControllerに例外ハンドラを書いてそれに応じてrenderするtemplateを振り分ける、という方法はできれば避けたいですね。

Rails覚えたての頃は、そちらの方法で実装していました。

totutotu.hatenablog.com

totutotu.hatenablog.com

実際に最初に静的ページで実装してみると、もともとRailsで用意されているpublic/hoge.htmlを使うことになるとは思いますが、エラーページにナビゲーションバーやフッターを追加してその内容が変わっていくのであれば、あまり賢くないように思います。いちいち変更するのはとても面倒そうです。

そこでRailsconfig.exceptions_appという設定があり、それをうまく使うことでエラー処理を行うことが出来るのでそれを使おう、ということになります。

rambulanceを試してみる

この方法を用いている、yuki24さんが作られているgemを使いながらこの方法についてみていきたい。

github.com

まずはgemを追加してbundle install

# Gemfile
gem 'rambulance'
$ bundle install

そしたらranbulance:installでファイルのテンプレートを生成します。-eオプションで特定のテンプレートエンジンを指定できます。

$ rails g rambulance:install -e slim

Railsではproductionで動かしてもアドレスがlocalhost127.0.0.1だと本番用のエラーページを出してくれません。ranbulanceはその辺も対応してくださってます。素敵すぎる。。

以下の様なURLでエラーページにアクセスすることができます。

localhost:3000/rambulance/***

ここまで使い進めてやはりつまずいたのは、exceptions_appを用いているというところ。。

exceptions_appは3.2から追加された機能で、例外発生時に呼ばれる例外処理アプリケーションを設定するというもの。デフォルトではActionDispatch::PublicExceptions.new(Rails.public_path)が使用される。Release Noteからは以下。

Added config.exceptions_app to set the exceptions application invoked by the ShowException middleware when an exception happens. Defaults to ActionDispatch::PublicExceptions.new(Rails.public_path).

参考: Railsのエラーハンドリング - 一分一秒真剣勝負!

こいつでRails標準のActionDispatch::PublicExceptionsを独自のコントローラに差し替えることができます。

middlewareレベルでExceptionsをrescueするActionDispatch::PublicExceptionsクラスのコードは以下。読むととても勉強になります。

rails/show_exceptions.rb at f49d20ef36c2d339e7a988fdc52981cdb95af22f · rails/rails · GitHub

ですが、例外が発生した場合はApplicationControllerまで届かずActionDispach::PublicExceptionsにrescueされてそちらのcontrollerに処理が委託されるので、ApplicationControllerで定義しているインスタンスメソッドやincludeしているApplicationHelperなどのヘルパーメソッドは使えなくなってしまう。

僕の場合はspのviewのlayout切り替えをここで行っていたりstylesheetの読み込み用のメソッドを用意したりしていたので結構つらみがあった。

やっぱり動的にやるのきつい。。

yuki24さんもおっしゃるように、よほど動的にしないといけないケース以外では静的ページとしてエラーページを用意する方が今のところよさそうかなと思いました。。結局メンテナンスのときなど、HTTPサーバーのレイヤーからエラーを出さなければいけないときは別途対応が必要ですし。

この方の記事も読んでおくとRailsでのエラー処理の考えが深まります。。

kami30k.com

雑に学んだことをまとめると、ApplicationControllerで拾った例外でview振り分けるのでは(ActionController::RoutingError は ApplicationControllerに到達する前に例外が発生しているので)見た目の解決にしかなってないのでよくなくて、やるならActionDispatch::PublicExceptionsで委託するcontrollerを変えないといけないのだけど、それだとApplicationController経由しないから色々つらいよ、みたいな感じ。。。

yuki24さんの結論は「そこまでして動的にやる意味あるんですかね?」とのこと。。。w

参考: Railsでエラーページを動的に - Qiita

つらい

ということで結局静的ページでやることにしました。つらい

pg_dumpの実行時にパスワード入力を省略する

pgではpg_dump実行時に必ずインタラクティブなパスワードの入力を求められるのですが、cron jobでのpb_dump実行時に、パスワードの入力を省きたいって感じのことです。どうやらパスワードを渡す方法はないみたいですね。

PostgreSQL公式docのpg_dumpのところ

-wオプションのところで以下のような記述が。

-w –no-password パスワードの入力を促しません。 サーバがパスワード認証を必要とし、かつ、.pgpassファイルなどの他の方法が利用できない場合、接続試行は失敗します。 バッチジョブやパスワードを入力するユーザが存在しない場合にこのオプションは有用かもしれません。

ふむ、.pgpassなるファイルがあるのか。

d.hatena.ne.jp

公式doc

31.15. パスワードファイル

.pgpassというファイルをホームディレクトリに配置することで、pgは勝手にそれをパスワードとして使用してくれるみたいです。

.pgpassのフォーマットは以下のようにします。

hostname:port:database:username:password

最初の4フィールドに関してはワイルドカードもありみたいです。また、

Unixシステムにおいて、.pgpassの権限はグループ、他者へのアクセスをすべて拒否しなければなりません。 これはchmod 0600 ~/.pgpassといったコマンドによって行います。 権限をこれよりも緩くすると、このファイルは無視されます。

とのことなので、

$ sudo chmod 0600 ~/.pgpass

としておきましょう。

これで、

$ pg_dump -Ft -U USER_NAME -w DB_NAME > BACKUP_FILE

のように-wでパスワードを省略してpd_dumpを実行することができました。わーい

PostgreSQL初期設定 in EC2

以下を参考にさせていただきました。

http://dev.classmethod.jp/cloud/aws/install-postgresql-on-aws-ec2/

手順

PostgreSQLをインストールします。

$ sudo yum update -y
$ sudo yum install -y libxslt.i686
$ sudo yum install -y postgresql postgresql-server postgresql-devel postgresql-contrib postgresql-docs

バージョンを確認

$ psql --version

PostgreSQLのdataを初期化します。これは、PostgreSQLを使う上で一番最初に叩く必要があります。

$ sudo /sbin/service postgresql initdb

起動・停止・再起動は以下のようにします。

$ sudo /sbin/service postgresql start
$ sudo /sbin/service postgresql stop
$ sudo /sbin/service postgresql restart

chkconfigをonにしておきます。

$ sudo /sbin/chkconfig --list | grep postgresql
postgresql      0:off 1:off 2:off 3:off 4:off 5:off 6:off
$ sudo /sbin/chkconfig postgresql on
$ sudo /sbin/chkconfig --list | grep postgresql
postgresql      0:off 1:off 2:on  3:on  4:on  5:on  6:off

initdbやったら勝手に作成されるpostgresユーザのパスワードを設定してログインしてみます。PostgreSQLでは、このpostgresユーザがマスターユーザ的な扱いになるようです。

$ sudo passwd postgres
$ su - postgres

postgresユーザのまま、今度はPostgreSQLの設定ファイルをいじっていきます。

$ vi /var/lib/pgsql9/data/postgresql.conf

まずはpostgresql.conflisten_addresses*にします。

listen_addresses = '*'                  # what IP address(es) to listen on;

今度はpg_hba.confをいじっておきます。以下をファイルの最後に追記します。

$ vi /var/lib/pgsql9/data/pg_hba.conf
## ファイル内有効行全コメント→末尾に追加
local   all     all     trust
host    all     all     0.0.0.0/0       md5

ユーザ設定

では今度は実際のアプリケーションで使うユーザの作成・設定をしていきます。

実行ユーザはpostgresで。

$ su - postgres

以下のようにしてユーザを作成できます。

$ createuser -AdPE testuser

そしたら以下のようにしてそのユーザが使うデータベースを作成します。

$ createdb -E UTF8 -U testuser -W testdb

次に、exitしてLinux側でもユーザを作成しておきます。PostgreSQLは基本的にLinuxユーザとDBのユーザが一致するようになっています。

$ sudo adduser testuser
$ sudo passwd testuser

確認・使い方

ここまでで初期設定は終了です。確認してみます。

ログインします。

$ su - testuser

以下で、データベースの一覧を表示できます。

$ psql -l

データベースへの接続。SQLを叩けるプロンプトに入ります。

$ psql -d database_name