そういうこともある

エンジニア的な何かの、プログラミングとかイベントレポートとか読書感想文

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

f:id:sktktk1230:20171212153754p:plain

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

読めるようにするまで

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

読んだ箇所

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

どんな使い方だっけ?

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

instance_variable_namesメソッドは配列を返します。配列のインスタンス名には"@"記号が含まれます。

class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_variable_names # => ["@x", "@y"]  

引用:RAILS GUIDES:instance_variable_names

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

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

f:id:sktktk1230:20180228174817p:plain

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

1. activesupport > lib > active_support > core_ext > object > instance_variables.rb
# frozen_string_literal: true

class Object

省略

  # Returns an array of instance variable names as strings including "@".
  #
  #   class C
  #     def initialize(x, y)
  #       @x, @y = x, y
  #     end
  #   end
  #
  #   C.new(0, 1).instance_variable_names # => ["@y", "@x"]
  def instance_variable_names
    instance_variables.map(&:to_s)
  end
end

まず、 instance_variables.map() を見てます

instance_variables を調べてみると

instance_variablesメソッドは、レシーバのオブジェクトが持っているインスタンス変数の名前を配列に入れて返します。

Ruby 1.9 Ruby 1.8では配列中の変数名は文字列ですが、Ruby 1.9ではシンボルになります。

class Book
  def initialize(title, price)
    @title = title; @price = price
  end
end
book = Book.new("Programming Ruby", 2000)
p book.instance_variables

["@title", "@price"] (Ruby 1.8の場合)

[:@title, :@price] (Ruby 1.9の場合)

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

インスタンス変数の名前を配列で取得しています。そしてその配列に対して map を実行しています

mapは

mapメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。collectメソッドの別名です。

numbers = ["68", "65", "6C", "6C", "6F"]
p numbers.map {|item| item.to_i(16) }

[104, 101, 108, 108, 111]

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

ブロックの戻り値を集めて配列にするメソッドです

次に .map(&:to_s) を見てみます

&: は配列の各要素に対して to_s を実行しているということです
たとえば、

[1, 2, 3].map(&:to_s)
=> ["1", "2", "3"]

ということです
※詳しい解説は@kasei-san氏のこちらの記事がわかりやすいかと思います
qiita.com

つまり、def instance_variable_names はレシーバのインスタンス変数名を配列として取り出すメソッドになります

読んでみて

今回は、前回書いた instance_values を読んでいたので、すんなりと読めました shitake4.hatenablog.com