Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord includes. Specify included columns

I have model Profile. Profile has_one User. User model has field email. When I call

Profile.some_scope.includes(:user) 

it calls

SELECT users.* FROM users WHERE users.id IN (some ids) 

But my User model has many fields that I am not using in rendering. Is it possible to load only emails from users? So, SQL should look like

SELECT users.email FROM users WHERE users.id IN (some ids) 
like image 979
ibylich Avatar asked Sep 13 '12 06:09

ibylich


People also ask

How does includes work in Rails?

Rails provides an ActiveRecord method called :includes which loads associated records in advance and limits the number of SQL queries made to the database. This technique is known as "eager loading" and in many cases will improve performance by a significant amount.

What is eager loading in Rails?

Eager loading is a way to find objects of a certain class and a number of named associations. Here I share my thoughts on using it with Rails. What are N + 1 queries? It mainly occurs when you load the bunch of objects and then for each object you make one more query to find associated object.


2 Answers

Rails doesn't have the facility to pass the options for include query. But we can pass these params with the association declaration under the model.

For your scenario, you need to create a new association with users model under the profile model, like below

belongs_to :user_only_fetch_email, :select => "users.id, users.email", :class_name => "User" 

I just created one more association but it points to User model only. So your query will be,

Profile.includes(:user_only_fetch_email) 

or

Profile.includes(:user_only_fetch_email).find(some_profile_ids) 
like image 192
Mohanraj Avatar answered Oct 06 '22 00:10

Mohanraj


If you want to select specific attributes, you should use joins rather than includes.

From this asciicast:

the include option doesn’t really work with the select option as we don’t have control over how the first part of the SELECT statement is generated. If you need control over the fields in the SELECT then you should use joins over include.

Using joins:

Profile.some_scope.joins(:users).select("users.email") 
like image 24
Chris Salzberg Avatar answered Oct 06 '22 00:10

Chris Salzberg