LoginSignup
6
6

More than 5 years have passed since last update.

Object#tapでログ出力のためだけにローカル変数を使う人生にサヨナラを告げよう

Last updated at Posted at 2016-04-07

概要

下記のようなコードで foo の戻り値をログ出力する際、どうしてますか?

def foo(opts)
  if opts
    "BAR"
  else
    "FOO"
  end
end

こうやってローカル変数を使って出力していた時期がありました

def foo(opts)
  r = if opts
        "BAR"
      else
        "FOO"
      end
  p r
  r
end

いまわかってるのは3つの方法

  • Object#tap
  • tapp (gem)
  • Object#display

Object#tapでローカル変数を排除する

結論、こんな感じに書き換えできます

def foo(opts)
  if opts
    "BAR"
  else
    "FOO"
  end.tap{|r| p r}
end

if..endの末尾に .tap{|r| p r} を加えるだけ

これで動く理由は参考資料でご確認ください(まるなげ

tapp (gem)なるもの

コメントで tapp を紹介いただきました (thx! yancya)

require "tapp"
def foo(opts)
  if opts
    "BAR"
  else
    "FOO"
  end.tapp
end

まさにこれ。

Object#display なるもの

コメントで Object#display を紹介いただきました (thx! riocampos)

def foo(opts)
  if opts
    "BAR"
  else
    "FOO"
  end.display
end

標準メソッドにこんなものがあったとはっっ!

使い分け

  • Object#tap: Loggerで出力するとき。わりと本番用?
  • tapp (gem): ともかく仕掛けておいて、あとで全部削除したいとき。grepしやすい
  • Object#display: 出力先を一時的にfileにするとか、手軽に変えられるようにしたいとき

Object#tap はロギングが要件に組み込まれてる時にも使えます

require "logger"
$logger = Logger.new($stderr)
$logger.level = :debug
def foo(opts)
  if opts
    "BAR"
  else
    "FOO"
  end.tap{|v| $logger.debug v}
end
foo(true)
#=> D, [2016-04-08T08:00:45.572860 #13340] DEBUG -- : BAR

Object#display は標準出力とかに出しにくいバイナリデータを出力するのに良さそうです

$to_file = open(Time.now.to_i.to_s, "wb")
def foo(opts)
  if opts
    "BAR"
  else
    "FOO"
  end.display($to_file)
end
foo(true)
#=> UNIXタイムなファイルが作成され、中身はBAR

参考資料

あとがき

Qiitaのエントリーに対する、具体的なユースケースという名のパクりエントリーでした、ごめんなさい
あと、エントリー名を "tapかわいいよ、tap" にしようとおもったら、完全に一致するブログがあったので変更

6
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6