Permalink
Browse files

TimeWithZone#advance: use #any? instead of #detect

  • Loading branch information...
1 parent 887434f commit 5120429c3138d46490a1c4a611ebd93410f4f885 @gbuesing gbuesing committed Feb 9, 2009
Showing with 1 addition and 1 deletion.
  1. +1 −1 activesupport/lib/active_support/time_with_zone.rb
@@ -230,7 +230,7 @@ def ago(other)
def advance(options)
# If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
# otherwise advance from #utc, for accuracy when moving across DST boundaries
- if options.detect {|k,v| [:years, :weeks, :months, :days].include? k}
+ if options.any? {|k,v| [:years, :weeks, :months, :days].include? k}
method_missing(:advance, options)
else
utc.advance(options).in_time_zone(time_zone)

10 comments on commit 5120429

@nate
nate commented on 5120429 Feb 9, 2009

Why any? over detect?

@peburrows

@nate: detect returns the object found, any? returns a boolean, which is all that’s needed here.

@joshsusser
Contributor

Enumerations are excessive when there is a clearer way to express what you mean:

unless (options.keys & [:years, :weeks, :months, :days]).empty?

(Or change unless to if and reverse the if and else clauses.)

@Roman2K
Roman2K commented on 5120429 Feb 9, 2009

Josh: +1

Except that when there’s an else clause, I prefer using if instead of unless. In this case:

if (options.keys & [:years, :weeks, :months, :days]).any?

Even with no else clause, I find if foo.any? to be more obvious than unless foo.empty? which I consider a double negative.

@pdcawley

How using a guard clause? Something like:

[:year, :weeks, :months, :days].each do |each|
  return method_missing(:advance, options) if options.has_key?(each)
end
utc.advance(options).in_time_zone(time_zone)

Or coerce the options into a duration and let the duration decide.

@raggi
Contributor
raggi commented on 5120429 Feb 9, 2009
options.values_at(:year, :weeks, :months, :days).compact.empty?
@raggi
Contributor
raggi commented on 5120429 Feb 9, 2009

still, +1 on josh

@Roman2K
Roman2K commented on 5120429 Feb 9, 2009

raggi: +1 for values_at! Plus, since any? returns true if any element is non-nil, your line can be simplified as (when using the if form):

options.values_at(:year, :weeks, :months, :days).any?
@gbuesing
Contributor

Productive conversation thread. I took the suggestion above, so now this line reads:

if options.values_at(:years, :weeks, :months, :days).any?

because it looked a little cleaner than the block syntax, and read nicely, i.e., “if any values at years, weeks, months, days, then …”

As a nice-to-have, it seems a bit faster — I did a simple benchmark, the results are kind of interesting:

http://pastie.textmate.org/385041

Array#empty? looks to be faster than #any? (at least for this example), but it didn’t seem worth flipping around the logic of the if clause just to chase those extra few cycles.

@joshsusser
Contributor

Nice, I like the values_at trick to avoid the call to keys. Thanks for doing the benchmarks.

Please sign in to comment.