我想根据无法在单个查询中汇总的复杂标准对Person
模型对象进行排序 - 因此在命名范围内。现在我使用类方法:
def Person.very_complicated_sorting
Person.all.sort { |x,y| x.bunch_of_calculations <=> y.bunch_of_calculations }
end
有没有办法让这个可链接? E.g。
Person.tallest.very_complicate_sorting.youngest
其中tallest
和youngest
是两个命名范围。
答案 0 :(得分:1)
不幸的是,这是不可能的。
命名范围的工作方式是“懒惰地”构建一组SQL参数,在您实际尝试对它们执行某些操作之前,这些参数不会被评估。例如,以下命名范围链:
people = Person.tallest.youngest
将不导致运行任何数据库查询,它实际上导致ActiveRecord::NamedScope
对象存储在people
变量中。只有当您访问或遍历该对象时,才会运行SQL并加载对象。
您的问题是您的排序方法没有在SQL中表达,它是一组Ruby条件。当Rails到达你的sort_by
时,它必须去获取并实例化Person
对象,以便它可以在它们上运行你的条件。完成后,您将拥有Array
个对象,而不再是NamedScope
个对象。
答案 1 :(得分:0)
您的very_complicated_sorting
应该在Person
模型中。
你不能在方法中写Person.all
,否则就无法链接。
请保持:
def self.very_complicated_sorting
sort_by { |x,y| x.bunch_of_calcultaions <=> y.bunch_of_calculations }
end
答案 2 :(得分:0)
如果您使用Sequel而不是ActiveRecord作为数据库库,则可以执行此操作。它允许您在模型上使用def_dataset_method
来创建在Datasets上运行的方法(其中包含模型);只要您的方法返回数据集,您就可以根据需要链接它们。例如:
class Person < Sequel::Model
def_dataset_method :active_only do
filter :active=>true
end
def_dataset_method :sort_much do
order :name, :age.desc
end
end
active_peeps = Person.active_only.sort_much
peeps_active = Person.sort_much.active_only
要留在数据集域中,您只需使用可表示为SQL的方法。您不能期望从数据库中请求某些记录,然后在它们上执行复杂的仅使用Ruby的逻辑(比如,通过在Ruby Hash中查找的object_id
对它们进行排序),然后然后继续在生成的数组上执行SQL。 Ruby不会在您的数据库上运行(pl/Ruby除外)。
或者,您可以直接进入Ruby数组,然后以任何顺序链接您喜欢的任何Ruby方法,如果它们都在数组和返回数组上运行。您必须在代码中明确决定何时从数据库中获取结果,然后再对数组进行操作。