William Notowidagdo Kiranatama Staff
Knowledge


Probably you already know about n+1 queries problem, read this post if you want to learn how to detect those kind of queries. For example:
class User < ActiveRecord::Base
  has_many :items
end

class Item < ActiveRecord::Base
  belongs_to :user
end
If we have 2 users, and several items we have controller like this:
def index
  @users = User.find(:all)
end
and in the view we have something like this:
<% @users.each do |user| %>
    <%= user.items.collect(&:name) %>
<% end %>
If we watch the queries on the log, we should see something like this :
SELECT * FROM "users"
SELECT * FROM "items" WHERE ("items".user_id = 1) 
SELECT * FROM "items" WHERE ("items".user_id = 2) 
if we have 1000 items, that means we are doing 1000+1 queries! Off course we can fix it like this (eager loading):
def index
  @users = User.find(:all, :include => :items)
end
And now we only have two queries. Detecting it in our application is another matter. If we have huge project, detecting it can be hard work and time wasting. I found a cool plugin/gem that help detecting n+1 queries problem, called Bullet. You can install it as a gem:
sudo gem install flyerhzm-bullet --source http://gems.github.com
or as a plugin
script/plugin install git://github.com/flyerhzm/bullet.git
or you can build the gem right from the source from:
git clone git://github.com/flyerhzm/bullet.git
cd bullet
gem build bullet.gemspec
sudo gem install bullet --local
If you are using it as a gem, don't forget to include this in your environment.rb:
config.gem 'flyerhzm-bullet', :lib => 'bullet', :source => 'http://gems.github.com'
include this in development.rb, and remember not to use bullet on production:
config.after_initialize do
  Bullet.enable = true  
  Bullet::Association.alert = true
  Bullet::Association.bullet_logger = true
  Bullet::Association.rails_logger = false
end
You want to make two profiles in your Firefox, one for regular browsing, and one without caching enabled since sometimes it is not working in regular profile. So disable caching on your browser if you want to see pop-up box if we are doing n+1 queries. Also Bullet detect eager loading that is not used. I attached a screenshot so you can see it in action:

Bullet in action