How to avoid N + 1 request

I have the following models:

  • User
  • Possibility
  • PricingRule

is determined with the following relations:

  • The user has many pricing rules.
  • has one pricing rule

enter image description here

The idea is to get all abilities that meet some criteria and select a pricing rule for each one. However, a custom pricing rule for a specific ability can be defined for each user.

Currently I am getting all the mapping possibilities and iterating over them:

  • try to find the current ability that matches the user's pricing rule.
  • or the default pricing rule

I am using Rails and ActiveRecord and this is what I have so far:

user = User.first
Ability.all.map do |a|
  user.pricing_rules.matching_ability(a).first || a.pricing_rule
end

      

According to the setting of the user-on-demand pricing rule, the business must run. The general workflow is to get a pricing rule from an opportunity.

Any ideas or help to get me on the right track would be much appreciated.

EDIT:

Where the implementation runs matching_ability

:

def self.matching_ability(ability)
  where(name: ability.name)
end

      

+3


source to share


1 answer


You can "load" to avoid N + 1 queries, for example:

user = User.includes(pricing_rules: :abilities).first
Ability.includes(:pricing_rule).map do |a|
  user.pricing_rules.matching_ability(a).first || a.pricing_rule
end

      

You should see in the generated SQL what this will add LEFT OUTER JOIN

to your queries, so ActiveRecord only loads related records in two queries. Specifically, the user will be loaded with pricing_rules

and abilities

on each pricing_rule

, and the abilities will be loaded with pricing_rules

.



However, a matching_ability

using implementation where

can generate additional queries, returning you to the N + 1 problem. To take advantage of the "eager loading" in the first query, you might need to refactor to:

self.matching_ability(ability)
  select{|a| a.name == ability.name}
end

      

+2


source







All Articles