There Are Four Lights
There Are Four Lights

Reputation: 1426

Rails - iterate within has_many ActiveRecord result

Company has_many :profiles, through: :other_model
Profile has_many :companies, through:  :other_model

OtherModel belongs_to :profile
OtherModel belongs_to :company

As result of a query, I have a scope of Companies.

What's the more efficacious way to fetch all sub-enteties (profiles)?

Upvotes: 0

Views: 91

Answers (2)

Nimir
Nimir

Reputation: 5839

You could eager load the profiles when querying the Company model:

@companies = Company.where(foo: foo).includes(:profiles) 

Assuming the where query on the Company returned companies with ids 1,2,3 the above activerecord query should execute following two queries:

SELECT * FROM companies WHERE (foo = 'foo')
SELECT profiles.* FROM profiles
  WHERE (profiles.company_id IN (1,2,3))

Now the returned @companies will include corresponding profiles for each company and you could simply do: @companies.first.profiles to access the first company profiles

Note, fetching those profiles records is done without running any further database queries and this is the hole point of eager loading

Update:

Returned result will be in an ActiveRecord::Relation so to fetch all profiles at once you could do:

@profiles = @companies.collect(&:profiles)

Upvotes: 2

xlembouras
xlembouras

Reputation: 8295

If you have a belongs_to :company relation in your Profile model:

class Profile < ActiveRecord::Base

  belongs_to :company

end

means that ther is a company_id in your Profile model.

so you can do:

Profile.where(company_id: companies)

where companies is a Company ActiveRecord::Relation.

Which results in SQL:

"SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`company_id` IN (1, 2)"

UPDATE

Since you use an intermediate model OtherModel you can do:

Profile.where(id: OtherModel.where(company_id: companies).pluck(:profile_id))

Upvotes: 0

Related Questions