Rubyでメソッドチェーンを書く為に覚えておきたいメソッド | rails commit log流し読みを読んでみた

f:id:sktktk1230:20180726121250p:plain

1. 概要

@y_yagiさんのrails commit log流し読みを読んでいてわからなかったこと調べてみました

2. 読んだエントリ

y-yagi.hatenablog.com

3. わからなかったこと

PRの中の処理に書かれていた.tap ってなんだろう?

対象のPR

github.com

記述内容

if value.blank? && options[:prompt]
  tag_options = { value: "" }.tap do |prompt_opts|
    prompt_opts[:disabled] = true if options[:disabled] == ""
    prompt_opts[:selected] = true if options[:selected] == ""
  end
  option_tags = tag_builder.content_tag_string("option", prompt_text(options[:prompt]), tag_options) + "\n" + option_tags
 end

4. 調べてみた

tap が分からなかった為、どんなメソッドなのか調べてみました

obj.tap {|myself| block }

tapメソッドは、ブロック変数にレシーバ自身を入れてブロックを実行します。戻り値はレシーバ自身です。メソッドチェーンの中にtapメソッドをはさみ込み、ソースコードを簡潔にする目的で使われます。

次の例は、文字列中の文字のコードを10進数と16進数で表示するものです。

arr = "hello".bytes.to_a
p arr
arr = arr.collect {|byte| byte.to_s(16) }
p arr

この例は、tapメソッドを使えば次のように書けます。

"hello".bytes.to_a.tap {|arr| p arr }
  .collect {|byte| byte.to_s(16) }.tap {|arr| p arr }

[104, 101, 108, 108, 111]

["68", "65", "6c", "6c", "6f"]

引用:Rubyリファレンス:tap

5. さきほどのソースコードを読んでみる

さきほどの記述の tap の部分を見てみると

tag_options = { value: "" }.tap do |prompt_opts|
    prompt_opts[:disabled] = true if options[:disabled] == ""
    prompt_opts[:selected] = true if options[:selected] == ""
  end

ブロック引数の prompt_optstap のレシーバである { value: ""} となります
options[:disabled] == "" が真の場合は、 { value: ""}disabled: true が追加されます
options[:selected] == "" が真の場合は、 { value: ""}selected: true が追加されます