LoginSignup
3
1

More than 3 years have passed since last update.

Ruby on Rails のquery attributeを使ってみる

Last updated at Posted at 2020-06-18

結論: blank?とpresent?の代わりにattribute名?が使える(一部気をつける必要あり)

背景: integerのarrayを足しあげたかった(nilの可能性があり)

元々の私のコード...

[ここはhogekeyにもつObjectの配列].reject(|obj| !obj.hoge.nil?).sum(:hoge)

reject(|obj| !obj.hoge.nil?) でhogeがnilのものを取り除き、 sum(:hoge) でnilを取り除いたhogeを足しあげるつもりでした。

修正版

[ここはhogekeyにもつ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が弾かれても困りませんが、場合によっては困ることもあるかなと思いました。

ここまで読んでいただきありがとうございました。
間違い等あればご指摘くださいまし、修正いたします。
(この記事は会社とは関係ありません)

3
1
0

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