0

我通过定义如下方法向 ActiveRecord 模型添加了自定义排序:

class MyClass < ActiveRecord::Base
  belongs_to :parent_model #this would be the many in a has_many relationship

  def <=>(other)
    self.att <=> other.att
  end
end

可以这么说,比较中实际使用的逻辑比这个例子要复杂一些,不是用 SQL 可以完成的。

由于此类仅用作包含模型中的嵌套字段,因此似乎没有直接的位置来对结果集进行排序。在控制器中,:my_class 是包含的一部分,用于急切加载,但在视图之前我不会对对象数组做任何其他事情(当我执行 form.fields_for :my_class 时)。我真正想要的是能够使用我的逻辑排序来做相当于 default_scope 的事情,但我认为这是不可能的。现在,我唯一的选择似乎是在控制器中添加一个额外的行,只是为了对这个结果进行排序,但这似乎不是正确的做法。

我在这里缺少什么更优雅的东西吗?

4

2 回答 2

0

最好的方法是设置数据库以进行 SQL 排序,并在范围/查找中提供 :order 选项。一旦加载的对象数量超过某个阈值,在控制器中进行排序将非常昂贵。特别是如果您试图限制列出的记录数。

如果排序真的比排序这一列比那一列更复杂。您应该考虑向数据库添加排序键列。您已经清楚地制定了一些排序方法,通常涉及比较从对象状态派生的两个值。只需使用 before_create/save 回调将该值存储在新的 sort_key 列中的数据库中,并按此排序结果。

任务示例:

按优先级排序,但截止日期为星期五的记录排在所有其他记录之前。使用 sort_key 列

class Task < ActiveRecord::Base
  def calculate_sort_key
    key = due_date.wday == 5 ? "0" : "1"
    key += prioirty.to_s
    self.sort_key = key.to_i
  end

  before_save :calculate_sort_key
  default_scope :order => "sort_key"
end
于 2009-11-30T17:21:37.223 回答
0

我无法测试这是否可行,但您可以尝试匿名关联模块,如下所示:

class ParentModel < ActiveRecord::Base
  has_many :my_class do
    # Sort the result set...  
  end
end
于 2009-11-30T17:27:37.887 回答