Tin*_*n81 2 ruby activerecord ruby-on-rails
在我的Rails应用程序中,我有以下关联:
class Person < ApplicationRecord
has_many :payments
def sales_volume(range)
payments.in_range(range).sum(&:amount)
end
...
end
Run Code Online (Sandbox Code Playgroud)
class Payment < ApplicationRecord
belongs_to :person
def self.in_range(range)
select { |x| range.cover?(x.date) }
end
...
end
Run Code Online (Sandbox Code Playgroud)
在我的控制器中,我正在......
@people = Person.all.sort_by { |p| p.sales_volume(@range) }
Run Code Online (Sandbox Code Playgroud)
......它有效.
不幸的是,它产生了很多N + 1个查询.
有没有办法显示每个销售量person而不为每个人生成单独的SQL查询?
加成:
我已经尝试过急切加载......
@people = Person.all.includes(:payments).sort_by { |p| p.sales_volume(@range) }
Run Code Online (Sandbox Code Playgroud)
......但那也没有用.查询数量仍然相同.
首先,让我们重写一下这个in_range方法ActiveRecord
def self.in_range(range)
where(date: range)
end
Run Code Online (Sandbox Code Playgroud)
现在,那sales_volume.让我们说吧
def self.with_sales_volume(range)
joins("LEFT JOIN payments ON payments.user_id = users.id").
merge(Payment.in_range(range)).
group('users.id').
select('users.*, SUM(payments.amount) AS sales_volume')
end
Run Code Online (Sandbox Code Playgroud)
最后
@people = Person.from(Person.with_sales_volume(@range), :t).order('t.sales_volume DESC')
Run Code Online (Sandbox Code Playgroud)
这是个主意.我已经这么做了很多次,但是如果没有尝试并拥有所有信息,那真的很难.我想你可以解决它以防万一.如果你使用的是rails 5,你可以使用left_joins