I was looking through our RoR code and I came across
def estimate_remaining
documents.inject(0.0) {sum, d sum + d.estimate_remaining}
end
It turns out that this can be changed to
def estimate_remaining
documents.to_a.sum(&:estimate_remaining)
end
thanks to some extensions to Enumerable in Active Support. I find this much easier to read; the former requires you to know some serious Ruby, though the latter takes advantage of a symbol trick that I don't really understand (&:estimate_remaining). (Thanks to this blog for the .to_a trick) I was hoping to do something similar to another method,
def documents_completed
i = 0; documents.each {d i += 1 if d.completed}; i #.nitems
end
which counts the number of documents under the parent project that are completed. A quick look in the Rails API documentation shows that sum() is the only aggregate method they added to Enumerable. So I decided to add count() myself. I shamelessly borrowed the sum() code and modified it to look like so:
I saved this in [PathToRailsApp]/config/initializers/count.rb (Rails 2 environment). Now my code to count completed documents looks like this:module Enumerable # Calculates a count by evaluating elements. Examples: # # payments.count { p p.price > 50 } # payments.count(&:overdue) # # This is instead of payments.inject { sum, p p.overdue ? sum + 1 : sum } # # The default identity (sum of an empty list) is zero. # However, you can override this default: # # [].count(Payment.new(0)) { p p.price > 50 } # => Payment.new(0) # def count(identity = 0, &block) return identity unless size > 0 if block_given? map(&block).count else inject(0) { sum, element element ? sum + 1 : sum } #i = 0; map { element i += 1 if element}; i #This may be faster
end end end
def documents_completed
documents.to_a.count(&:completed)
end
Much cleaner! Obviously, this method is only useful if you need to count records that satisfy some sort of criteria (otherwise .length would suffice). Also, this might be more efficient done via SQL, but in my case Document.completed is a Ruby method (or "virtual column"), not an SQL column.
1 comments:
Comment from Wordpress
Rabbit:
Hi. The symbol trick you mentioned is explained pretty well here:
http://blog.hasmanythrough.com/2006/3/7/symbol-to-proc-shorthand