2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

nilではない場合にのみメソッドを呼び出したい場合について(try, &.)

Last updated at Posted at 2019-01-21

include?などで対象のオブジェクトがnilの場合にNoMethodErrorを発生させずに、nilではない場合にのみメソッドを実行したり条件分岐させたりしたい場合の処理について調べてつつ色々試したのでメモ。

通常

sample = nil

if sample.include?("a")
  sample
else
  sample.to_a << "a"
end
#=>NoMethodError: undefined method `include?' for nil:NilClass
#["a"]の入った配列を返すことなくエラーで処理が止まってしまう。

実際には違うコードですが、要はinclude?で真の場合と偽の場合で処理を分岐させたかった時にこのエラーが表示されるようになってしまったので、対処法を調べました。

unless nil?を使う

sample = nil

unless sample.nil?
  if sample.include?("a")
    sample
  else
    sample.to_a << "a"
  end
else
  sample.to_a << "a"
end
# =>["a"]

冗長すぎる

tryメソッド(Active Support)

sample = nil

if sample.try(:include?, "a")
  sample
else
  sample.to_a << "a"
end
#=>["a"]

&.(Ruby)

sample = nil

if sample&.include?("a")
  sample
else
  sample.to_a << "a"
end
#=>["a"]

今回はtryと&.で解決しました。なお、nil以外のレシーバに対して呼び出した際に少し違いがあり、メソッドが呼び出せない時にtryはnilを返し、&.はエラーを吐くといった違いがあるようです。(try!にすれば&.と同様にエラーにできます。)

#ArrayクラスにStringクラスメソッドを使ってみる。

sample = ["a", "b", "c"]

sample.upcase
#=>NoMethodError: undefined method `upcase' for ["a", "b", "c"]:Array

sample.try(:upcase)
#=> nil

sample&.upcase
#=>NoMethodError: undefined method `upcase' for ["a", "b", "c"]:Array

sample.try!(:upcase)
#=>NoMethodError: undefined method `upcase' for ["a", "b", "c"]:Array

try!にすると&.と同じくエラー吐くようにできますので、両者の違いはなくなりつつありますが、調べてみると&.の方が高速なようなので、今回は&.を使用しました。

# 参考
Active Support コア拡張機能(https://railsguides.jp/active_support_core_extensions.html)

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?