LoginSignup
5
1

More than 1 year has passed since last update.

Railsにおける真偽判定いろいろ(present? / blank? / empty? / nil? / any? / all? / zero? / ActiveRecord::Type::Boolean)

Last updated at Posted at 2021-06-25

Ruby, Railsにはnilやブランク、その他ブロック条件の真偽値判定を行うメソッドがかなりあります。ついつい無思考に present?やblank?を使ってしまいがちですが、使い分けることでより明示的になるかなと思ってます。

真偽判定いろいろ

  • present?(Railsのみ)
  • blank?(Railsのみ)
  • empty?
  • nil?
  • any?
  • all?
  • zero?
  • ActiveRecord::Type::Boolean.new.cast

present? と blank?

present?!blank?と同じ。
https://github.com/rails/rails/blob/d66e7835bea9505f7003e5038aa19b6ea95ceea1/activesupport/lib/active_support/core_ext/object/blank.rb#L23

"".present? #=> false
[].present? #=> false
{}.present? #=> false
nil.present? #=> false

# 配列の要素はnilでも存在してると判定される
[nil].present? #=> true

present?が true の時はレシーバを返し、falseの時はnilを返したい時はpresenceが使える。

a = "hoge"
b = a.presence
# これと同じ
b = a.present? ? a : nil

empty? と nil?

blank? = empty? + nil?のこと。 訂正。blank?のtrue判定はより広く、これはよくある誤解なので注意。詳しくはコメント参照。@scivolaさんありがとうございますm
empty?はnilには呼べない。nilのハンドリングはちゃんとやれってことか。それが面倒なら blank?を使えと。ちなみに、nil?は Object#nil?なので、全クラスのインスタンスで使える。

"".empty? #=> true
[].empty? #=> true
{}.empty? #=> true
nil.empty? #=> NoMethodError

nil.nil? #=> true

any? と all?

any?は配列やハッシュに対して、条件一致する要素が少なくとも一つはあるか判定する。基本的にはブロックを渡して使う(正規表現も渡せる)。all?全部条件を満たすか判定する。

[1, 2, 3].any? { |i| i > 3 } #=> false
[1, 2, 3, 4].any? { |i| i > 3 } #=> true
[1, 2, 3, 4].all? { |i| i > 3 } #=> false
[1, 2, 3, 4].all? { |i| i < 5 } #=> true

{ name: "taro", age: 20 }.any? { |k, v| k == :name } #=> true

zero?

0 かどうか判定するメソッドまであったりする。Numeric#zero?なので、IntegerやFloatなどのNumeric以外には使えない。

0.zero? #=> true

ActiveRecord::Type::Boolean.new.cast

true / false 判定は、"true" / "false"のように文字列になると正しく行われない。ActiveRecord::Type::Booleanを使うとこの辺もよしなにやってくれる。もちろん Rails だけ。

ActiveRecord::Type::Boolean.new.cast("false") #=> false

全部 boolean になるわけではなく、戻り値は true/false/nil。

# false判定されるもの
false, 0, "0", :"0", "f", :f, "F", :F, "false", :false, "FALSE", :FALSE, "off", :off, "OFF", :OFF

# nil判定されるもの
nil, ""

おまけ

||= と &.

||=は nil ガードと呼ばれ、左辺が falsy な値だった場合だけ右辺が評価される。

a = nil # falseでも同じ
a ||= "hoge"
p a #=> "hoge"

a ||= "foo"
p a #=> "hoge" 再代入されない

&.はぼっち演算子と呼ばれ、続けてメソッドを呼び出して使う。レシーバが nil だった場合、強制的に nil を返す。

nil.upcase #=> NoMethodError
nil&.upcase #=> nil

感想

個人的にはこれらのメソッドはあんまり好きじゃなくて、==とかで明示的に書く方が好きだけど、確かにシンプルに書けるので、使い所は選んでいきたいですね!

5
1
2

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
5
1