user8071606
user8071606

Reputation:

Rails activerecord - how to inherit all child associations?

So in my application I have the models People and Outfits. In my show controller for people, I get the list like this:

@people = Person.where("description LIKE ?", "%#{params[:description]}%")

And in my view I show the outfits of each person like this:

<% @people.each do |person| %>
  <p> Name: <%= person.name %> </p>
  <% @outfits = person.outfits %>
  <% @outfits.each do |outfit|
    <p> Name: <%= outfit.name %> </p>
    <p> Description: <%= outfit.description %> </p>
  <% end %>
<% end %> 

But loading the outfits for each person, as I load many people on the page, takes too long. Is there some way I can inherit the outfits of each person so I don't have to wait so long for the page to load? Or is the only way to speed this up to make an index between outfits and people? Thanks for any help

Upvotes: 0

Views: 84

Answers (3)

Hammad Maqbool
Hammad Maqbool

Reputation: 59

You can use .joins or .includes

If you have a table full of Person and you use a :joins => outfits to pull in all the outfit information for sorting purposes, etc it will work fine and take less time than :include, but say you want to display the Person along with the outfit name, description, etc. To get the information using :joins, it will have to make separate SQL queries for each user it fetches, whereas if you used :include this information is ready for use.

Solution

Person.includes(:outfits).where("description LIKE ?", "%#{params[:description]}%")

Upvotes: 0

max
max

Reputation: 102222

Use a join to load the associated records:

@people = Person.eager_load(:outfits)
                .where("description LIKE ?", "%#{params[:description]}%")
                .limit(20) # optional

Otherwise you have what is called a N+1 query issue where each iteration through @people will cause a separate database query to fetch outfits.

And yes the outfits.person_id or whatever column that creates the association should have a foreign key index. Using the belongs_to or references macro in the migration will do this by default:

create_table :outfits do |t|
  t.belongs_to :person, foreign_key: true
end

Upvotes: 2

Oscar Luza
Oscar Luza

Reputation: 404

you should set a limit like this:

@people = Person.where("description LIKE ?", "%#{params[:description]}%").limit(20)

change the number according to your preference.

Upvotes: 0

Related Questions