为什么'where'方法会进行不必要的数据库调用?

时间:2013-11-10 11:52:46

标签: ruby-on-rails ruby postgresql activerecord rubymine

我在Ruby 1.9.3上运行Rails 3.2.10,使用PostgreSQL作为db和RubyMine来调试我的代码。在调试时,我注意到了这一行:

@monkeys = Monkey.where(user_id: 2)

进行2次数据库调用并生成以下日志:

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

为什么第二次通话?我怎么能避免它?

这是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

更新

我重新启动了服务器,它就像接受的答案所说的那样有效。

1 个答案:

答案 0 :(得分:3)

实际上,行@monkeys = Monkey.where(user_id: 2)根本不执行SQL查询。它只生成一个Relation对象:

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

只有在Rails需要数据时才会执行查询,例如,如果您在.each上调用.all.first.to_sRelation

如果您将Relation存储在变量@monkey中,并且代码中的@monkey.where(is_active: true).first类似于执行第二次查询,那么.where(is_active: true)部分会定义另一个关系除了@monkey中存储的那个。

我很确定上面的行不会产生两个SQL查询。控制器,帮助器或视图中有一些触发第二个查询的内容。您可以在Rails控制台中尝试,如果在那里键入@monkeys = Monkey.where(user_id: 2)会发生什么?什么是输出,登录到您的log/development.log