In each & every real life scenario our utmost focus is on saving the time. In terms of DB we can save this time by reducing the number of SQL queries fired. This is what Eager Loading is used for.
Rails provide us 3 methods to perform Eager Loading:-
1) #includes 2)#preload 3)#eager_load
All these 3 methods eager load the associated model's data to save time by not firing queries again and again.
To explain these 3 methods i am using the following Active Record Class & associations:
class Category < ActiveRecord::Base
has_many :equipments, dependent: :destroy
end
class Equipment < ActiveRecord::Base
belongs_to :category
validates_presence_of :category
end
Rails use 2 ways to preload the data. Firstly it uses seperate db queries to get association data & secondly it uses single query which is created using table-joins.
Explanation for the 3 Eager Loading methods is :
(A) preload fires sepearte queries to get associations data. Ex:-
Category.preload(:equipments)
# SELECT "categories".* FROM "categories"
# SELECT "equipment".* FROM "equipment" WHERE "equipment"."category_id" IN (3, 4)
(B) eager_load fires single query to get associations data using joins. Ex:-
Category.eager_load(:equipments)
# SELECT "categories"."id" AS t0_r0, "categories"."created_at" AS t0_r1, "categories"."updated_at" AS t0_r2, "categories"."name" AS t0_r3, "categories"."available" AS t0_r4, "equipment"."id" AS t1_r0, "equipment"."category_id" AS t1_r1, "equipment"."name" AS t1_r2, "equipment"."equipment_count" AS t1_r3, "equipment"."created_at" AS t1_r4, "equipment"."updated_at" AS t1_r5 FROM "categories" LEFT OUTER JOIN "equipment" ON "equipment"."category_id" = "categories"."id"
C> includes let rails decide whether to fire single query or seperate query depending on the situation. Ex:-
Category.includes(:equipments)
# SELECT "categories".* FROM "categories"
# SELECT "equipment".* FROM "equipment" WHERE "equipment"."category_id" IN (3, 4)
Use of references method:-
We can also give conditions with any of the 3 eager loading methods like:
Category.includes(:equipments).where("equipment.equipment_count = ?", 0)
But this will raise a warning as
warning:-
It looks like you are eager loading table(s) (one of: categories, equipments) that are referenced in a string SQL snippet
Because includes method fires seperate query and we have not joined categories table with equipment table, so rails is not aware of how to compute equipment.equipment_count. Thus we need to direct rails to use the particular table where it will search the fields mentioned in where clause. And for this purpose we use references method like:-
Category.includes(:equipments).where("equipment.equipment_count = ?",5).references(:equipment)
eager_load method only fires 1 single query by using joins, so it automatically associates the field_name with the desired table. So it need not have references method.
Category.eager_load(:equipments).where("equipment_count = ?", 5)
The above query works absolutely fine because it uses eager_loading.
In Rails 4, the best practise is to use includes along with references .
0 Comment(s)