結論: blank?とpresent?の代わりにattribute名?が使える(一部気をつける必要あり)
背景: integerのarrayを足しあげたかった(nilの可能性があり)
元々の私のコード...
[ここはhogeをkeyにもつObjectの配列].reject(|obj| !obj.hoge.nil?).sum(:hoge)
reject(|obj| !obj.hoge.nil?)
でhogeがnilのものを取り除き、 sum(:hoge)
でnilを取り除いたhogeを足しあげるつもりでした。
修正版
[ここはhogeをkeyにもつObjectの配列].select(&:hoge?).sum(:hoge)
reject(|obj| !obj.hoge.nil?)
が select(&:hoge?)
になりました。
hoge?がtrueに評価されるものをselectするようにしました、ここが今回学んだことです。
attribute名?という表現ができることです。
解説
類似記事が既にあります
私の元々のコードはBad smellのするよくないコードだったようです。(参考ページ)
Rails本体のコードも見てみました。
このcase文が該当の箇所のようです。
case文もまとめると、、、
まずtrue なら true、false, nil なら falseですね
when true then true
when false, nil then false
次にレシーバに指定のattributeがある場合とない場合で大きく切り分けられるようです。
if !type_for_attribute(attr_name) { false }
if Numeric === value || !value.match?(/[^0-9]/)
!value.to_i.zero?
else
return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
!value.blank?
end
elsif value.respond_to?(:zero?)
!value.zero?
else
!value.blank?
end
!type_for_attribute(attr_name) { false }
にてレシーバに該当のattribute名がなければtrueとなります。
その上で、Numeric === value || !value.match?(/[^0-9]/)
の場合(数字)、0の時false、それ以外はtrueとなります。
数字以外の場合は、falseの時はfalse、それ以外の時はblank?の結果が帰るようです。
次はレシーバに該当のattribute名がある場合です。
value.respond_to?(:zero?)
で zero?を持つ場合は !value.zero?
が評価され0の時false、それ以外はtrueとなります。
zero?を持たない時は、!value.blank?の結果が帰るようです。
まとめ
多くの場合でattribute名.blank?
やattribute名.present?
の代わりに使えるなと思いました。
気をつけたいのは、0の時にfalseになるということですね。
参考記事でも言及されていました。
私がしたかったことは単純に足し上げだったので0が弾かれても困りませんが、場合によっては困ることもあるかなと思いました。
ここまで読んでいただきありがとうございました。
間違い等あればご指摘くださいまし、修正いたします。
(この記事は会社とは関係ありません)