首页 > 解决方案 > 是否可以指定链式范围查询的顺序

问题描述

我目前正在做这样的链式范围查询

Enrollment.active.occurs_today

是否可以对查询进行排序,以便在.active之前查询.occurs_today并防止延迟加载?希望类似于下面的东西

Enrollment.active.eval.occurs_today

标签: ruby-on-railsactiverecord

解决方案


并不总是赞赏的是,链式作用域的顺序并不重要。链式作用域正在构建包含所有条件的单个查询,然后当您执行查询(例如,通过请求记录或计数)时,将使用组合条件检索记录。

例外是 rails 控制台,每个作用域在输入时都会在其中执行。

如果您有伪范围(执行返回id然后查询的查询),您可以将其实现为类方法并安排将其他范围作为参数传递给类方法以首先执行它们。一个可能的实现可能是......

def self.occurs_today(*scopes)
  result = scopes.inject(all) {|relation, scope| relation.send(scope)}    
  where(id: result.select { |s| s.occurs_on?(Date.current) }.map(&:id))
end

然后你可以做

Enrollment.occurs_today(:active)

或几个范围

Enrollment.occurs_today(:active, :priority)

在这两种情况下,select都将在已经作用域的关系上执行。

或者,我认为您可以通过更改现有occurs_today范围来看到性能的改进(以及范围顺序的自动识别)。

而不是选择所有记录...

scope :occurs_today, -> { where(id: all.select { |s| s.occurs_on?(Date.current) }.pluck(:id) }

...仅选择当前范围的记录...

scope :occurs_today, -> { where(id: select { |s| s.occurs_on?(Date.current) }.pluck(:id) }

推荐阅读