2

Is there a better way to declare this?

if current_user.received_replies.unread.count > 0

What I'm trying to do is match condition only if there's at least one unread object.

Martin
  • 11,216
  • 23
  • 83
  • 140

3 Answers3

4
unless current_user.received_replies.unread.empty?
  # ...
end

Or, if your if has an else, switch the cases (because unless/else is fugly as hell):

if current_user.received_replies.unread.empty?
  # ...
else
  # ...
end
Niklas B.
  • 92,950
  • 18
  • 194
  • 224
3

I'd use:

if current_user.received_replies.unread.any?

From the docs:

= Array.any?

(from ruby core)
=== Implementation from Enumerable
------------------------------------------------------------------------------
  enum.any? [{|obj| block } ]   -> true or false

------------------------------------------------------------------------------

Passes each element of the collection to the given block. The method returns
true if the block ever returns a value other than false or nil. If the block
is not given, Ruby adds an implicit block of {|obj| obj} (that is any? will
return true if at least one of the collection members is not false or nil.

       %w{ant bear cat}.any? {|word| word.length >= 3}   #=> true
       %w{ant bear cat}.any? {|word| word.length >= 4}   #=> true
       [ nil, true, 99 ].any?                            #=> true
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • 1
    That is not quite equivalent if the list contains falsy items. In the domain of `ActiveRecord` it might be viable, but I've seen a lot confusion about this where people thought it was just the negation of `empty?`, which is not true in general. – Niklas B. Apr 26 '12 at 23:33
  • @NiklasB. Wow I never noticed that. Kind of nasty that `[false].any?` is `false`. – Andrew Marshall Apr 26 '12 at 23:38
  • @Andrew: Why wouldn't it be? Usually this function is to check if a predicate holds for *any* of the items, like in `[1,2,3].any? { |x| x > 2 }`. It's kind of unfortunate that it also works without a block (I don't see where it would be useful). – Niklas B. Apr 26 '12 at 23:39
  • @NiklasB. Well that's my point, the version without a block is misleading and doesn't immediately seem to convey its check for truthyness. I agree that it shouldn't exist. – Andrew Marshall Apr 26 '12 at 23:47
  • I find the non-block version quite useful, but then I know that my array will contain truthy elements. If you don't know what is in your array the block is great to provide deeper inspection of the elements. If I have a array of unknown element types, I think I have a bigger problem than whether `any?` works without a block. – the Tin Man Apr 26 '12 at 23:49
  • @theTinMan: Sure, I just think if you use it with the purpose of checking if a collection is non-empty, `!x.empty?` is more direct. After all, the `x.any?` version is confusing to both those people who know about the "real" purpose of `any?` (which is only sensible if a block is involved) and those who don't know about it and conclude that `any?` must be the negation of `empty?`. – Niklas B. Apr 26 '12 at 23:59
1

This could be a little bit better :

unless current_user.received_replies.unread.empty?
Cydonia7
  • 3,744
  • 2
  • 23
  • 32