Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find_by inside a scope is firing 2 queries

I am using Rails 4.2.3 and ruby 2.2.1

I have written a scope in roles model as follows:

app/models/role.rb

scope :default, -> { find_by(default: true) }

Now when I run

> Role.default

#this is the output I got.

Role Load (0.1ms)  SELECT  `roles`.* FROM `roles` WHERE `roles`.`default` = 1 LIMIT 1 
Role Load (0.1ms)  SELECT `roles`.* FROM `roles`
=> []

As you can see this fires 2 queries and returns wrong result.

I tried with class method instead of scope

def self.default
  self.find_by(default: true)
end

Now when I run

Role.default

#this is the output I got

Role Load (0.2ms)  SELECT  `roles`.* FROM `roles` WHERE `roles`.`default` = 1 LIMIT 1
=> nil

With class method find_by is working properly.

I am not able to understand what am I doing wrong here. Any help would be appreciated. Thanks in advance.

like image 795
abhima9yu Avatar asked Jul 09 '15 22:07

abhima9yu


2 Answers

ActiveRecord, the object relational mapping system built into Rails, provides you with a set of methods to use in your scopes to abstract out the database queries. Those methods are listed here:

http://guides.rubyonrails.org/active_record_querying.html#retrieving-objects-from-the-database

In your case, you will want to use the where query.

scope :default, -> { where(default: true) }

like image 193
Mike Avatar answered Nov 11 '22 13:11

Mike


You shouldn't be using find_by inside a scope - find_by actually executes a database query.

You should only be using methods that return further scopes, for example where, limit, order and so on.

like image 24
Frederick Cheung Avatar answered Nov 11 '22 12:11

Frederick Cheung