Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • EAGER LOADING IN RAILS

    • 0
    • 5
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 462
    Comment on it

    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)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: