環境
- Ruby 2.4.1
- Rails 5.1.4
みなさんこんにちは。
あいづちくんです。
例えば、Railsで開発をしていて、ルーティングエラー発生時に処理を差し込みたいという場面があったとします。
ルーティングエラーに処理を差し込む場合、モンキーパッチを当てることで対応できます。
今回の例では、ルーティングエラーのエラーの種類をFATALからWARNに変更しています。
ActionDispatchにモンキーパッチをあてて制御するパターンです。
以下の例ではconfig/initializers/logger.rb
に追加しています。
unless Rails.env.development?
class ActionDispatch::DebugExceptions
alias_method :org_log_error, :log_error
def log_error(request, wrapper)
if wrapper.exception.is_a? ActionController::RoutingError
Rails.logger.warn wrapper.exception.message
else
org_log_error request, wrapper
end
end
end
end_
ただ、モンキーパッチを当てたくない場合もあると思うので、そんなときには別の方法でも対応できます。
ちなみに、ActionDispatch::DebugExceptionsのlog_error周りはRails4とRails5で若干の違いがあったりするので、やはりモンキーパッチを当てるのは避けたほうが良いのかもしれません。
今回のパターンでは影響ありませんが、rails4系と5系ではlog_errorの引数が変わっており、バージョンによって影響が受けそうな印象を受けました。
Rails 4.2.10
ActionDispatch
def log_error(env, wrapper)
logger = logger(env)
return unless logger
exception = wrapper.exception
trace = wrapper.application_trace
trace = wrapper.framework_trace if trace.empty?
ActiveSupport::Deprecation.silence do
message = "\n#{exception.class} (#{exception.message}):\n"
message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
message << " " << trace.join("\n ")
logger.fatal("#{message}\n\n")
end
end
Rails 5.1.4
ActionDispatch
def log_error(request, wrapper)
logger = logger(request)
return unless logger
exception = wrapper.exception
trace = wrapper.application_trace
trace = wrapper.framework_trace if trace.empty?
ActiveSupport::Deprecation.silence do
logger.fatal " "
logger.fatal "#{exception.class} (#{exception.message}):"
log_array logger, exception.annoted_source_code if exception.respond_to?(:annoted_source_code)
logger.fatal " "
log_array logger, trace
end
end
ということで、次回は別の方法をご紹介しようと思います。