2

我有一个项目模型和一个开发者模型。我有为特定开发人员计算项目的“趣味性”的概念:

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)

不过,我不知道该怎么做,因为对我来说如何覆盖范围并不明显。有什么建议吗?

4

1 回答 1

0

假设您不需要对orderProject 类使用标准 ActiveRecord 查询方法,您可以像任何其他类方法一样覆盖它:

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
于 2012-10-11T16:29:27.563 回答