Search code examples
ruby-on-railsrubypostgresqlactiverecordrubymine

Why is the 'where' method making an unnecessary database call?


I am running Rails 3.2.10 on Ruby 1.9.3, use PostgreSQL as the db and RubyMine to debug my code. While debugging, I noticed that, this line:

@monkeys = Monkey.where(user_id: 2)

Makes 2 database calls and generates the following logs:

Monkey Load (0.6ms)  SELECT "monkeys".* FROM "monkeys" WHERE "monkeys"."user_id" = 2
Monkey Load (1.4ms)  SELECT "monkeys".* FROM "monkeys" WHERE "monkeys"."user_id" = 2 AND "monkeys"."is_active" = 't' LIMIT 1

Why the second call? How can I avoid it?

This is the migration for the Monkey Model:

class CreateMonkeys < ActiveRecord::Migration
  def change
    create_table :monkeys do |t|
      t.belongs_to :user, null: false
      t.belongs_to :monkey_template, null: false

      t.boolean :is_redeemed, null: false, default: false
      t.boolean :is_active, null: false, default: true

      t.datetime :activation_time
      t.datetime :expiration_time
      t.datetime :redemption_time
      t.timestamps
    end

    add_index :monkeys, :user_id
  end
end

UPDATE

I restarted the server and it works as the accepted answer suggests.


Solution

  • Actually the line @monkeys = Monkey.where(user_id: 2) does not do a SQL query at all. It just generates a Relation object:

    Monkey.where(user_id: 2).class   #=> ActiveRecord::Relation < Object
    

    The query is only performed if Rails needs the data, for example if you call .each, .all, .first or .to_s on the Relation.

    If you store the Relation in a variable @monkey and have something like @monkey.where(is_active: true).first in your code than a second query is performed, because the .where(is_active: true) part defines another Relation in addition to the one that was stored in @monkey.

    I am pretty sure the line above will not make two SQL queries. There is something in the controller, helpers or views that trigger the second query. You can try that in your Rails console, what happens if you type @monkeys = Monkey.where(user_id: 2) in there? What is the output, what is logged into your log/development.log?