Railsでルーティングエラーに処理を差し込む モンキーパッチ編
PICK UP POST

Railsでルーティングエラーに処理を差し込む モンキーパッチ編

環境

  • Ruby 2.4.1
  • Rails 5.1.4

みなさんこんにちは。

通勤時間長いエンジニアの金子です。

例えば、Railsで開発をしていて、ルーティングエラー発生時に処理を差し込みたいという場面があったとします。

ルーティングエラーに処理を差し込む場合、モンキーパッチを当てることで対応できます。

今回の例では、ルーティングエラーのエラーの種類をFATALからWARNに変更しています。

ActionDispatchにモンキーパッチをあてて制御するパターンです。

以下の例ではconfig/initializers/logger.rbに追加しています。

1
2
3
4
5
6
7
8
9
10
11
12
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::DebugExceptions#log_error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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::DebugExceptions#log_error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

ということで、次回は別の方法をご紹介しようと思います。

TAG

金子 将範
エンジニア 金子 将範 rubyist

新しいことや難しい課題に挑戦することにやりがいを感じ、安定やぬるい事は退屈だと感じます。 考えるより先に手が動く、肉体派エンジニアで座右の銘は諸行無常。 大事なのは感性、プログラミングにおいても感覚で理解し、感覚で書きます。