Rails

エラー処理について②


初めに

過去にエラーの処理に関する記事を書きました

それがこれ

railsでエラー処理

この記事を書いたところ


Railsのエラー処理については、たしかにrescue_fromを使うと様々なエラーを処理することができますが、個人的にはあまり多用すべきではないと思っています。


という話を聞き少し調べてみました。


rails guidesでは

rails guidesにはrescure_fromのところで


rescue_fromにExceptionやStandardErrorを指定すると、Railsでの正しい例外ハンドリングが阻害されて深刻な副作用が生じる可能性があります。よほどの理由がない限り、この指定はおすすめできません。


のように書いてあった。


アドバイスでは

もらったアドバイスでは


例外処理はかなり奥が深いですし、下手に実装するとかえって発生したエラーを迷宮入りさせてしまうことにもなりかねないので、原則は「エラーが起きても何もしない、フレームワークの共通処理に任せる」だと考えています。


という話だったのですが実際にアプリを作成する場合間違いなくエラーゼロなんていうのも難しいと思うので

 

 

ある程度のエラーハンドルは必要そう。

多用するのが良くないといってもどのくらいなら良いのかわからない…

 

 

そこでgitlabのソースコードを読んでみた。

 

rescue_fromで例外を補足してエラーページを出力しているコードがこちら

rescue_from Encoding::CompatibilityError do |exception|

log_exception(exception)
render "errors/encoding", layout: "errors", status: 500
end

rescue_from ActiveRecord::RecordNotFound do |exception|
log_exception(exception)
render_404
end

rescue_from(ActionController::UnknownFormat) do
render_404
end

rescue_from Gitlab::Access::AccessDeniedError do |exception|
render_403
end

rescue_from Gitlab::Auth::TooManyIps do |e|
head :forbidden, retry_after: Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window
end

rescue_from GRPC::Unavailable, Gitlab::Git::CommandError do |exception|
log_exception(exception)

headers['Retry-After'] = exception.retry_after if exception.respond_to?(:retry_after)

render_503
end

上の三つは最初からrailsに搭載されているもので

エンコードのエラー,activerecord,actioncontrollerのエラーを取得している。

下の三つは独自のもので名前的に

権限関係と....よくわかんない(笑)

とりあえずgitlabで例外を補足していたのはテンプレートがなかった時レコードがなかった時エンコードの問題があったときだった。

 

エラーを補足した場合log_exceptionでログを出力していてそれがこのコード

def log_exception(exception)

Gitlab::Sentry.track_acceptable_exception(exception)

backtrace_cleaner = request.env["action_dispatch.backtrace_cleaner"]
application_trace = ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception).application_trace
application_trace.map! { |t| " #{t}\n" }
logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}"
end

ActionDispatchとか知らんしなんで単純に

logger.error "#{exception.class.name} : #{exception.message}"

にしないのかよくわからん

まあとにかく

rescue_from exception

はしないようにします:cop_tone1: