シングルページアプリケーションを書く時にいっつも似たようなコードを書いていたので、勢い余って gem にしました。
使い方
gem 'restful_error'
以上。
そうすると、
def show
@post = Post.find(param[:id])
end
みたいなアクションがあったとして、 GET /posts/10.json
すると
{ status_code: 404, response_message: "要求されたリソースが存在しません"}
みたいに json がちゃんと返ってくる。(もちろん status code は404)
他のステータスも自由に raise できる。
class PostsController < ApplicationController
before_action do
raise RestfulError[401] unless current_user
# or
raise RestfulError::Unauthorized unless current_user
end
end
自分でエラーを定義する時は、継承するか
class ::NoSession < RestfulError[404]; end
# or
class ::NoSession < RestfulError::NotFound; end
http_status メソッドを定義して Helper を include する
class OAuthController < ApplicationController
# all you need is status_code
class RequireTwitterLogin < StandardError
include RestfulError::Helper
def http_status = :unauthorized # or 401
end
end
response のカスタマイズ
デフォルトで、 html, json, xml に応答する。
response_message のとこは
ja:
restful_error:
active_record/record_not_found: 要求されたリソースが存在しません
not_found: ページが存在しません
で設定可能。
active_record/record_not_found
は ActiveRecord::RecordNotFound
専用、 not_found
は 404 エラー汎用となる。
response_message は include Helper
で追加されるが、メソッド定義を上書きするか、 @response_message
に値を入れれば優先される 。
class RequireLogin < StandardError
def initialize(provider = 'Unknown')
@provider = provider
end
def http_status
:unauthorized
end
def response_message
I18n.t('restful_errors.require_login', provider: provider)
end
end
以下のいずれかを置いておけば、レスポンスを柔軟にカスタマイズ出来る。
views/restful_error/show.html.erb
views/restful_error/show.json.jbuilder
views/restful_error/show.xml.erb
(もちろん haml でも rabl でもそこはご自由に)
中身の話
ActiveRecord::RecordNotFound
が raise された時にステータスコードがちゃんと 404 になる仕組みが Rails にもともとあって、これは config/application.rb
とかで
config.action_dispatch.rescue_responses.merge!(
'MyGreatError' => :not_found,
としておくと、 raise MyGreatError
で 404 を返してくれる。
resutful_error は http_status
がなくてもここからステータスを取っており、
ActiveRecord::RecordNotFound
ではちゃんと 404 になるし、 ActiveRecord::RecordInvalid
ではちゃんと 422 になる。
ステータスコードのリストみたいなのどっかにないかなーと思ったら Rack::Util
にあったのでそれを使ってます。
全てのステータスコードにシンボルが対応していて、数字でもシンボルでもどっちでも使えるようになっている。便利。
例外には message メソッドがあるのだけどこれは i18n に対応していないので使用しない。クラス名、 reason phrase (404 なら not_found みたいなやつ) の順に i18n のキーを検索して適用することにしている。
FAQ
どこがrestfulやねん
すいません、誇大広告です。
いちおう気持ちとしては、'RESTってhttpのURLとかメソッドとかを、ちゃんと本来の意味で使おうね' っていう運動だと理解しており、適切なステータスコードで結果を返すのもその方向性だろうと思って、この名前にしています。
ツッコミをお待ちしております