Railsのソースコード読んでみる | Active Support silence_warnings編

f:id:sktktk1230:20180726124729p:plain

普段仕事で使っているRuby on Railsですが、ソースコードを読む機会もなかなかないので、試しにやってみることにしました

読めるようにするまで

以前書いた記事で読めるようにするまでの設定を画像キャプチャ付きで解説しましたので、よろしければこちらをご参照下さい
shitake4.hatenablog.com

読んだ箇所

silence_warnings を今日は読んでみようと思います

どんな使い方だっけ?

読んでみる前にまずは使い方を調べてみます
Railsの日本語ドキュメントを見てみると

ブロックが継続する間$VERBOSEの値を変更し、その後リセットします。

silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }

suppressメソッドを使用すると例外の発生を止めることもできます。このメソッドは、例外クラスを表す任意の数値を受け取ります。suppressは、あるブロックの実行時に例外が発生し、その例外が(kind_of?による判定で)いずれかの引数に一致する場合、それをキャプチャして例外を発生せずに戻ります。一致しない場合、例外はキャプチャされません。

# ユーザーがロックされていればインクリメントは失われるが、重要ではない
suppress(ActiveRecord::StaleObjectError) do
  current_user.increment! :visits
end

引用:RAILS GUIDES#2.13 警告・例外の抑制

ソースコードを読んでみる

1. railsプロジェクトのactivesupportにある機能ですので、activesupportディレクトリのlib配下で def silence_warnings を探してみます

f:id:sktktk1230:20180323135822p:plain

2. 該当箇所が1箇所あったので、みてみます

1. activesupport > lib > active_support > core_ext > kernel > reporting.rb
# frozen_string_literal: true

module Kernel
  module_function

  # Sets $VERBOSE to +nil+ for the duration of the block and back to its original
  # value afterwards.
  #
  #   silence_warnings do
  #     value = noisy_call # no warning voiced
  #   end
  #
  #   noisy_call # warning voiced
  def silence_warnings
    with_warnings(nil) { yield }
  end

省略

end

with_warnings メソッドにブロックを渡してます。 そのブロック内で yield しているので、元は silence_warnings に渡したブロックです
たとえば、

silence_warnings { puts 'ブロック実行' }

このように書いた場合は、 {}の内容がwith_warnings へそのままブロックとして渡すという感じになります

※ ブロックの詳しい説明は@kidach1氏のこちらの記事を参考にしてください qiita.com

silence_warnings の処理を見てみます

省略

# Sets $VERBOSE for the duration of the block and back to its original
# value afterwards.
def with_warnings(flag)
  old_verbose, $VERBOSE = $VERBOSE, flag
  yield
ensure
  $VERBOSE = old_verbose
end

省略

仮引数flag には nil が入ります

次に変数の初期化処理  old_verbose, $VERBOSE = $VERBOSE, flag で、$VERBOSE がどんなものなのかわからなかったので、調べてみます

冗長メッセージフラグです。Rubyインタプリタへの コマンドラインオプション -v でセットされます。
警告レベルは三段階あり、それぞれ以下の通りです。

  • nil
    • 警告を出力しない
  • false
    • 重要な警告のみ出力 (デフォルト)
  • true
    • すべての警告を出力する

$VERBOSE に nil, false 以外を代入すると値は true になります。
$VERBOSE の値はコマンドラインオプション -W でも設定できます。 -W0 オプションで nil、 -W1 オプションで false、 -W2, -W オプションで true が設定されます。 -v オプションや -w オプションを指定した場合は true が設定されます。
$VERBOSE はグローバルスコープです。
引用:Ruby2.5.0リファレンスマニュアル#variable $-v

with_warningsメソッド内では

  1. ブロック実行前に $VERBOSEnilを入れることで警告を出力しないモードへと変更
  2. yield でブロックを実行
  3. ブロック実行後、もともと設定されていた$VERBOSE へ設定し直すという処理になります

読んでみて

普段は使っていない機能だったので、どんな挙動するのか手探りで読んでました。使い所がまだ理解できていないので、このような機能があることを覚えておき、使えるようにしておくのが、良さそうだと思いました