我有一个Project模型和一个Developer模型。我有为特定开发人员计算项目“兴趣”的概念:
class Project < ActiveRecord::Base
def interestingness_for(developer)
some_integer_based_on_some_calculations
end
end
我认为它会很整洁,而不是像Project.order_by_interestingness_for(bill)
这样的东西,能够说出来
Project.order(:interestingness, :developer => bill)
并且它是一个范围,而不仅仅是一个函数,所以我可以做像
这样的事情Project.order(:interestingness, :developer => bill).limit(10)
我不知道该怎么做,因为对我来说如何覆盖范围并不明显。有什么建议吗?
答案 0 :(得分:0)
假设您不需要为Project类使用标准的ActiveRecord order
查询方法,您可以像任何其他类方法一样覆盖它:
def self.order(type, options)
self.send(:"special_#{type}_calculation_via_scopes", options)
end
然后诀窍是确保您创建所需的计算方法(根据您的兴趣和其他算法而有所不同)。并且计算方法仅使用范围或其他AR查询接口方法。如果您不习惯使用查询接口将方法逻辑转换为SQL等效项,则可以尝试使用Squeel DSL gem,它可以根据您的具体计算直接使用该方法。
如果您可能需要经典的order
方法(这通常是一个安全的假设),那么请不要覆盖它。为此目的创建代理非ActiveRecord对象,或使用不同的命名约定。
如果你真的想要,你可以使用别名来达到类似的效果,但如果第二个参数(在这种情况下为'options')在Rails进展时突然出现另一个意义,它可能会长期产生意想不到的后果。以下是您可以使用的示例:
def self.order_with_options(type, options = nil)
if options.nil?
order_without_options(type)
else
self.send(:"special_#{type}_calculation_via_scopes", options)
end
end
class << self
alias_method_chain :order, :options
end