Rails group count

When you do group in Rails (SQL GROUP BY), count will return an ActiveSupport::OrderedHash. Sometimes you want the sum count (count of all the results, not by group). You can do count.keys.count, however this has serious performance issues if you have a lot of groups in the results.

I wrote an ActiveRecord scope that will override the count method to perform a more optimised count query (of course it will now return a FixNum instead of a Hash). You can use this in combination with Kaminari and get much more efficient calculation of total_pages and total_count.

Gemified (Ruby Gem): https://github.com/mrbrdo/active_record_group_count
Gist: https://gist.github.com/mrbrdo/5679455

Companion object in Ruby

Scala has this concept of a companion object. One of the things the companion object does is let you define class methods. In Ruby we usually use one of these two approaches:

We could have a similar construct to Scala. It seems Rails does something that clashes with defining the method ‘object’ in Kernel, so let’s call it companion instead.

Maybe not the most useful thing, but it looks tidy and nice, especially if you have a lot of class methods.

present? is killing Ruby

I don’t mean this literally, but have you ever seen code like this:

post = Post.first
if post.present?

If you think about it, the present? is not necessary. It’ll be either nil or it will be a record. But we don’t usually even think about it and we just use it everywhere. I’m talking about Rails developers.

What do you think, is it being abused?

On a side note, I would love to see Coffeescript’s existential operator in Ruby. It could actually be implemented with method missing, except for local variables.

Number of classes and methods in a Rails project

A relatively small Rails project has

n_methods = 746703
n_unique_method_names = 2500
n_classes = 2500
avg_methods_per_class = 298
# n_methods = ObjectSpace.each_object(Class).map{|c| c.methods + c.private_methods}.flatten.count
# n_unique_method_names = ObjectSpace.each_object(Class).map{|c| c.methods + c.private_methods}.flatten.uniq.count
# n_classes = ObjectSpace.each_object(Class).count
# avg_methods_per_class = n_methods / n_classes