以下の記事を読んで「えっ、こうやって書けるの?」と思ったサンプルコードがあったので自己理解のための記事です。
驚いたサンプルコードは以下です。
def fetch(id_or_object, model_class) case id_or_object when Numeric model_class.find(id_or_object) when model_class id_or_object else fail "Object type mismatch #{model_class}, #{id_or_object}" end end
目的がid_or_objectがid(=数値)かクラスかで処理を分岐することであるのはコードに雰囲気から分かるのですが、case式のwhenの条件に直接型を指定できるというのが驚きでした。
if文とPythonでいうisinstance相当の関数を使って実現するのだと思っていました。なぜこのコードが動くのか理解したいと思います。
1.Rubyではcase式のwhen条件では===で比較される
これは公式ドキュメントに記載があります。
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html#case
すなわちサンプルコードは以下のようにも書けるということです。
def fetch(id_or_object, model_class) if Numeric === id_or_object # ...省略 elsif model_class === id_or_object # ...省略 end
2.Rubyでは{値} === {クラス}は値がそのクラス型のインスタンスであるかを判定する
これはirbで実験すると分かります。
irb(main):003:0> String === "1" => true irb(main):004:0> String === 1 => false irb(main):005:0> Numeric === 1 => true irb(main):006:0> class Animal end => nil irb(main):007:0> dog = Animal.new => #<Animal:0x000000013b0d5c28> irb(main):008:0> Animal === dog => true irb(main):009:0>
ちなみに左右を逆にすると成立しません。
irb(main):001:0> "1" === String => false
以上でなぜこのサンプルコードで動くのかざっくりとは理解できました。


