そういうこともある

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

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

f:id:sktktk1230:20171212153754p:plain

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

読めるようにするまで

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

読んだ箇所

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

どんな使い方だっけ?

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

述語in?は、あるオブジェクトが他のオブジェクトに含まれているかどうかをテストします。渡された引数がinclude?に応答しない場合はArgumentError例外が発生します。

in?の例を示します。

1.in?([1,2])        # => true
"lo".in?("hello")   # => true
25.in?(30..50)      # => false
1.in?(1)            # => ArgumentError  

引用:RAILS GUIDES:in?

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

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

f:id:sktktk1230:20180403185950p:plain

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

1. activesupport > lib > active_support > core_ext > object > inclusion.rb
class Object
  # Returns true if this object is included in the argument. Argument must be
  # any object which responds to +#include?+. Usage:
  #
  #   characters = ["Konata", "Kagami", "Tsukasa"]
  #   "Konata".in?(characters) # => true
  #
  # This will throw an +ArgumentError+ if the argument doesn't respond
  # to +#include?+.
  def in?(another_object)
    another_object.include?(self)
  rescue NoMethodError
    raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
  end

省略

end

引数(another_object)に対してinclude?を実行しています

include?を調べてみます

array.include?(obj)

include?メソッドは、配列の要素に引数objが含まれていればtrue、なければfalseを返します。要素と引数objが同じかどうかの比較には==メソッドが使われます。

animals = ["dog", "cat", "mouse"]
puts animals.include?("cat")
puts animals.include?("elephant")
true
false

引用:Rubyリファレンス#include?(Array)

str.include?(other_str)

include?メソッドは、文字列の中に引数other_strの文字列が含まれるかどうかを調べます。含まれるときはtrue、含まれないときはfalseを返します。

s = "Supercalifragilisticexpialidocious"
puts s.include?("exp")
true

引用:Rubyリファレンス#include?(String)

mod.include?(other_mod)

include?メソッドは、クラスやモジュールが引数のモジュールother_modをインクルードしているかどうかを調べます。インクルードしていればtrueを、そうでなければfalseを返します。

親クラスがインクルードしているモジュールを指定してもtrueになります。

p String.include?(Comparable)
p String.include?(Enumerable)
p String.include?(Kernel)
true
true  (Ruby 1.9ではfalse)
true

引用:Rubyリファレンス#include?(Module)

rubyのinclude?の実装は3つあるみたいです(String, Array, Module)
another_object.include?(self) は引数のオブジェクトがレシーバに対してinclude?かどうかをチェックしています

そして、メソッドが実装されていない場合には、 ArgumentError を返すという処理になっていました

rescue NoMethodError
  raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
end

読んでみて

include? はよく使用していますが、in?はあまり馴染みがなかったので、挙動を学べたので、うまく使い分けなど出来るといいなと思います