何が言いたいかわかりにくいが、要は下記ケースだとtrueが返るという話。
[1] pry(main)> [1,2,nil].include?(nil)
=> true
nil
を含む配列に対して nil
を渡すと true
が返されます。
冷静に見れば当たり前な気がしますが、何となくnilの比較はfalseが返る思い込みみたいなのがあるというか、ちょっとモヤってしたので調べました。
調べたって言っても、ソースを見たらすぐわかりましたが。
[2] pry(main)> show-source Array#include?
rb_ary_includes(VALUE ary, VALUE item)
{
long i;
VALUE e;
for (i=0; i<RARRAY_LEN(ary); i++) {
e = RARRAY_AREF(ary, i);
if (rb_equal(e, item)) {
return Qtrue;
}
}
return Qfalse;
}
rb_equal
が何かというと ==
メソッドの事で、配列の中に nil
が含まれるということは、ループの中で nil == nil
が評価されることで true
が返されるという事になります。
https://docs.ruby-lang.org/ja/latest/function/rb_equal.html
[3] pry(main)> nil == nil
=> true
Activesupport の in?
メソッドも include?
を呼んでいるのでこちらの条件が当てはまります。
# activesupport/lib/active_support/core_ext/object/inclusion.rb
def in?(another_object)
another_object.include?(self)
rescue NoMethodError
raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
end
実際に今回の内容を調べるきっかけになったのは、以下みたいな条件で hoge=nil
なのに先に進んでしまいエラーになった事からでした。
# hoge => nil
# piyos => [1,2,nil]
return unless hoge.in?(piyos) # => trueが返るのでreturnされない
まぁそもそも hoge
に対して nil
チェックしたり、 piyos
に対して compact
を当てろって話ですけどね。。。