anonn023432
anonn023432

Reputation: 3120

Rails includes method when to add

So I've read a lot about the rails includes method but I'm still a bit confused about what's the best situation to use it.

I have a situation where I have a user record and then this user is related to multiple models like client, player, game, team_player, team, server and server_center.

I need to display specific attributes from the related models in a view. I only need around 1-2 attributes from a specific model and I don't use the others.

I already added delegates for example to get the server.name from player I can use server_name but in this situation do I include all of the tables from which I need the attributes or is there something else I do because I only need a couple of attributes from the model.

My query is as follows at the moment:

@user_profile = User
               .includes({:client => [:player, :team_player => [:team]]}, 
                        :game, 
                        {:server_center => :server})
               .where(game_id: @master.admin.games)

Upvotes: 2

Views: 3633

Answers (1)

Vishal Taj PM
Vishal Taj PM

Reputation: 1359

Includes ensures that all of the specified associations are loaded using the minimum possible number of queries.

Let say we have 2 models named User and Profile :

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

If we are iterating through each of the users and display the name of each user were name field resides in Profile model which has a association with User model, we would normally have to retrieve the name with a separate database query each time. However, when using the includes method, it has already eagerly loaded the associated person table, so this block only required a single query.

without includes:

users = User.all
users.each do |user|
  puts user.profile.name # need extra database query for each time we call name
end

with includes

# 1st query to get all users 2nd to get all profiles and loads to the memory
users = User.includes(:profile).all
users.each do |user|
  puts user.profile.name # no extra query needed instead it loads from memory.
end

Eager Loading is used to prevent N+1 query problems. basically it does left outer join and this plays an important role in speeding up request response or optimizing the queries. eg: if we are having huge amount users and if we want to iterate through those users and their corresponding profile. no of time which we will be hitting database will be equals to number of users. but if we are using includes it will keep all profile into memory later when we iterate through the users it will fetch from this memory instead of querying.

Eager loading may not always be the best the cure for our N+1 queries for eg: if you are dealing with some complex queries preferably looks for some caching solutions like Russian Doll caching etc.. still both method has his own pros & cons end of the day it's up to you to determine the best approach.

one useful gem which helps to detect N+1 query is bullet

Upvotes: 2

Related Questions