asiniy asiniy - 2 months ago 12
Ruby Question

rails 4 eager loading heavy association

I have an association between rails models.

There are three models which describe

product
properties:

Property
is associating the models, each property has a name and value.

class Property < AR::Base
belongs_to :product
belongs_to :property_name
belongs_to :property_value

class PropertyName < AR::Base
has_many :properties
validates :name, presence: true, uniqueness: true

class PropertyValue < AR::Base
has_many :properties
validates :value, presence: true, uniqueness: true


After searching via thinking-sphinx I get facets - property_values id & property_names id collections.

Using that result, I then try to find all properties for current list of
products
(to continue to filter those search results).

In the controller I use:

@property_names = PropertyName
.where(id: property_name_ids)
.includes(:property_values).where('property_values.id IN (?)', property_value_ids)


My view:

- @property_names.each do |property_name|
h4 = property_name.name
- property_name.property_values.pluck(:value).uniq.each do |property_value|
= check_box_tag ...
= label_tag ...


So, eager load does not work. Rails generate a lot of (n+1) queries for the database. What's going wrong? Why includes don't work?

Answer

Solved by me.

First of all, add a association has_many :property_values, -> { uniq }, through: :properties at property_names.

After that, I use this query:

  @property_names = PropertyName.where(id: property_name_ids).where.not(name: PropertyName.description)
    .includes(:property_values).where(property_values: { id: property_value_ids }).order('property_values.value')

All works!

Comments