LakTEK A Sri Lankan, A Rubyist and A Web Dude

[Rails Tips] Reduce Queries in ActiveRecord with :group

I thought of sharing some tips in Ruby on Rails development, which would come in handy especially if you are a newbie.  The cornerstone of all of Rails’ magic is ActiveRecord. As you know it’s an ORM, which hides all cumbersome and mundane SQL by a syntactic sugar coating. However, blind and lazy usage of ActiveRecord could really hurt your application’s performance.

I found this particular instance when revisiting code of an app, I have written in my early days of Rails. As a newbie overdosed with ActiveRecord’s magic, had written a blunt piece of code which looks horrible and also would make the app painfully slow.

1550 items in total (1350 Available, 150 Out of Stock and 50 Discontinued)

This was the expected summary output. At surface, displaying such a block seems trivial, right?

I had the following in the view:

<p><%= @all_items_count %> items in total (<%= available_items_count %> Available, <%= out_of_stock_items_count %> Out of Stock and <%= discontinued_items_count %> Discountinued)</p>

Then in the controller, I have explicitly assigned the ActiveRecord query results all four variables. (‘acts_as_state_machine’ plugin provides the count_in_state method.)

def index
   @all_items_count = Item.count :all
   @available_items_count = Item.count_in_state :available, :all
   @out_of_stock_items_count = Item.count_in_state :out_of_stock, :all
   @discontinued_items_count = Item.count_in_state :discontinued, :all
end

Technically this works. But can you spot the issue here? Lets get to terminal and inspect the app’s logs. When rendering this action, it sends a query to database to get each of the four values. Database queries are costly and will cause a slow response.

Better Solution?

If we could reduce the number of database queries this action would be very effective. So is there a way we could reduce the number of Database queries? Remember that we can group the results of an SQL query? You can specify the :group option in ActiveRecord’s query methods.

I modified the previous code to pass the :group option to the query:

def index
   @items_in_state = Items.count :all, :group => "state"
end

Now, instead of four queries we are making only one database query. With the group option passed, ActiveRecord will return the results in the form of a Hash. So we can now grab the count of items in each state.

Lets change our view to adapt to the changes we did in the controller.

<p><%= count_items("all") %> items in total (<%= count_items("available") %> Available, <%= count_items("out_of_stock") %> Out of Stock and <%= count_items("discontinued") %> Discontinued)</p>

Here, I used a simple helper method called `count_items` to make it more elegant. Here is what goes in the helper:

  def count_items(state)
    return @items_in_state.inject(0) { |count, s| count + s[1] } if state == "all"
    @items_in_state.fetch(state, 0)
  end

To return the total count, we could use `inject` method, which would iterate through the hash to take the sum.

Also, keeping the basics in mind, we should index the database fields which is queried regularly. In this case, it is better to index of the `state` column of the table.

Mistakes like this are very obvious and could be easily avoided if you do the things with a sense. However know the trade-offs, always keep an eye on what’s happening behind at the backstage. Don’t let the faithful genie to turn into a beast.


Ruby Best Practices

First of all sorry for letting this space go on a hiatus yet again.. Though I tried to make it a habit of posting regularly, other priorities didn’t allow me to do it as I wish. In last few months I had to run through lot of challenges in real life and in hacking, which I feel would be worthy to share. I promise that I will start posting them soon.

Meanwhile, I’m glad to inform you that I will also be contributing to Ruby Best Practices Blog, which is a collaborative effort organized by Gregory Brown of Prawn fame. Rest of the core team of RBP includes well experienced and interesting developers such as, James Britt, Kirk Haines, Robert Klemme, Jeremy McAnally, Sean O’Halpin and Magnus Holm. So if you are passionate in writing smart and robust Ruby code, you would really enjoy this blog.

Visit Ruby Best Practices blog.


Get mocked!

My first few days doing Maths in Advanced Levels was a nightmare. I usually sucked in Maths in high school and only because of my strong passion for IT made me do Maths (thats the only way in Sri Lanka to gain higher education in IT). I couldn’t grasp a single shit, other than knowing some greek characters on the board. The tutor was ruthless, and sarcastic at his best. To make the matters worse, the class was full of opposite sex, who were awaiting to LOL at any insult thrown. I just sounded total dumbass!

Tutor said I will not go beyond a simple pass even if I work my ass off. However, after two years of hard work, I proved him wrong by entering to University of Moratuwa, and pursue my childhood dream of a career in IT (Bonus: I also did found my better half at the same class). It was the mockery at the class, made me strong and motivated me to bring out the best in me.

It’s natural to feel humiliated and give up when you get mocked by others, but try to turn them into your own advantage. Don’t try to avert them or defend them. Let them mock you! Just keep believing in yourself and stick to what you do!


Professional Education is Bullshit!

Most of my university colleagues has this craze of following various professional education courses and certifications. They call it CIMA, BIT, BCS, ACS, SCJP, CCNA, MSDN, PMP and the list goes on. I don’t get the rationale behind this, What’s the benefit of having all these qualifications? What exactly you gain by spending such hefty amounts of money for these courses? Is it because you think you could decorate your CVs with all these bullshit? Or is it just for the sheer pleasure of seeing random Latin characters printed after your name?

As I know most of these courses focus on single line of technology or certain set of standards, which has no guarantee to be relevant in another 2 years time. Also, comparing with the academic education these courses doesn’t offer much diversity and depth either. You could easily get through these exams by parroting the mock question bank and puke it all at the exam. There is very little chance of anything retaining and absorbing to yourself.

The reality is those qualifications or the grades itself won’t make you brilliant. Those will just take you far away from the reality. It will give you and world that you are a qualified professional. But in reality, most of these people struggles to get things done and fails miserably at the real targets. Bill Gates, Steve Jobs, Sergy Brin and Larry Page they all have one thing common. All of them had to dropout from their academic careers, to reach their destiny. That doesn’t mean you need to dropout to make a difference. However, what is evident is that the stuff you do, the challenges you meet, the problems you solve and the experiences you gain during your academic career, are what makes you different from the rest of the stack.

Inspire yourself to gain some real life opportunities. Oragnize a Gig, Do a research (I mean a real one- not those tomfoolery), Start contributing to an open source project or create your own startup. Find something which matches your passions and engage with it. Don’t just waste your precious time and money, by blindly running after professional qualifications that won’t worth a shite.


Belated Resolutions

It is almost mid January and still this is the first post for new year. I’m looking at 2009 to be a switching year in my life. The days of adolescence have almost comes to its’ end and real life responsibilities seems to be creeping up. The days for bullshitting are numbered, and “I’m still learning” and “I’m still trying” will no longer be accepted as excuses. So it’s the high time to get real and face the music.

Here is what I will be looking to do this year (in no particular order)

  • Fix my sleeping pattern (and cut it short to 5 hours)
  • Have a regular workout routine.
  • Turn CurdBee into a solid web platform.
  • Keep on Blogging
  • Launch hackruby.com
  • Toastmastering for real (and be a competent communicator)
  • Horticulture
  • More Driving (only if I could fill my gas tank)
  • Avoid becoming an RSS/Twitter junkie
  • AND finish off this Degree, which sucks in big time!

← Before