はじめに
Railsのビューで、「画像があったら表示させる」みたいな処理を書く場面がありました。
存在確認のためのメソッドは、Rubyのもの、Railsのもの含め、いくつかあります。
ちょっと調べて、「よし、これで行こう!」とメソッドを選択してレビューに出したところ、おもいっきり玉砕したので、今後間違えないように備忘録として残しておきます。
環境
macOS Catalina Version 10.15.5
Ruby: 2.6.5
Ruby on Rails: 6.0.3
調査対象
- any?(Ruby)
- empty?(Ruby)
- nil?(Ruby)
- present?(Rails)
#動機
過去にも類似の記事はあり、実際に大部分、「rubyの真偽判定メソッド(nil?/empty?/blank?/present?)を検証してみた結果、興味深いことがわかった」に乗っからせていただきました。そのうえで、今回投稿に至った理由は、以下となります。
- 上記投稿においてany?メソッドが触れられていなかったが、any?の挙動についても確認したかった(今回直面したのが、配列絡みの問題だったため)
- 上記投稿のまとめの表では、
-「ある かどうかを聞くメソッド(present?等。何かあればtrueを返す)」
-「無い かどうかを聞くメソッド(empty?等。何も無ければtrueを返す)」
が並べて表記されていたが、「何かある場合に〇〇を返す」というように、条件の方向を揃えた表(present?と not empty?が比較できるような表)が欲しかった
※もちろん上記の表のメリットとして、present?とblank?が裏の関係になっていることがわかりやすい、等があります
なお、blank?は除外しています(present?の定義が!blank?のため)。
調査方法
rails consoleを使います。
test = XXX ←ここに色々代入していく
test.any?
!test.empty?
test.present?
!test.nil?
調査結果
| | any? | !empty?
(empty?の否定)| present?
(!blank?)|!nil?
(nil?の否定)|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| Ruby/Rails | Ruby | Ruby | Rails | Ruby |
|1
数字|NoMethodError| NoMethodError|true|true|
|"foo"
文字列|NoMethodError|true|true|true|
|{key: value}
ハッシュ|true|true|true|true|
|["foo"]
配列|true|true|true|true|
|true|NoMethodError|NoMethodError|true|true|
|false|NoMethodError|NoMethodError|false|true|
|nil|NoMethodError|NoMethodError|false|false|
|""
空|NoMethodError|false|false|true|
|" "
半角スペース|NoMethodError|TRUE|FALSE|true|
|{}
空ハッシュ|false|false|false|true|
|[]
空配列|false|false|false|true|
|[nil]
配列(要素がnil)|FALSE|TRUE|TRUE|TRUE|
※ any?
はEnumerableモジュールで定義されているため、配列やハッシュ以外で使おうとしてもNoMethodErrorとなります
要点
この結果から今後気を付けなきゃなと思ったところは、表内で大文字で強調していますが、改めて以下に記載しておきます。
- 半角スペースは、
!empty?
では存在するもの空ではないとみなされtrueを返し、present?
では空とみなされfalseを返す
↑(修正)@scivola 様よりコメントをいただき、修正および追記しました。ありがとうございました。
(追記)present?
(もといblank?
)は、空判定の出る範囲が広めであることに注意
例:false、nil、半角スペース以外に、全角スペース、タブ(\t)、改行(\n)、Unicode(\unnnn)等も空と判定される - 配列に
any?
を適用すると、**真の要素(=nilでない要素)**がある場合にtrueを返す。それ以外のメソッドは、真か否かに関係なく、要素があればtrueを返す。 - 素の
nil
に!nil?
って聞いてもfalseを返すが、[nil]
でできた配列に!nil?
と聞くとtrueを返す
その他
Railsで、exists?
というメソッドもあります。これは、データベースに特定の条件のデータが存在するか確かめるときに使うようで、ActiveRecord::Base
で定義されているメソッドとのことでした。そのことをつゆ知らず、当初調査対象に含めていましたが、すべてNoMethodError
を返されました。
学び
Qiita初投稿となりました。シンプルでごく当たり前の内容だとは思いますが、アウトプットのために調べる、整理する、といった過程を通じて理解を深める良い機会となりました。
定期的に、今後の自分(≒他人)にとって役に立つ記事を投稿していきたいと思います。
参考URL
rubyの真偽判定メソッド(nil?/empty?/blank?/present?)を検証してみた結果、興味深いことがわかった