【问题标题】:Default Logical Sort on Resultset Array RubyonRails结果集数组RubyonRails的默认逻辑排序
【发布时间】:2010-12-21 13:54:10
【问题描述】:

我通过定义如下方法向 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 的事情,但我认为这是不可能的。现在,我唯一的选择似乎是在控制器中添加一个额外的行,只是为了对这个结果进行排序,但这似乎不是正确的做法。

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

【问题讨论】:

    标签: ruby-on-rails activerecord enumerable


    【解决方案1】:

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

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

    任务示例:

    按优先级排序,但截止日期为星期五的记录排在所有其他记录之前。使用 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
    

    【讨论】:

      【解决方案2】:

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

      class ParentModel < ActiveRecord::Base
        has_many :my_class do
          # Sort the result set...  
        end
      end
      

      【讨论】:

      • 这种方法比在控制器中排序更容易和干燥。但它在控制器中也存在排序问题。即大型集合上的计算时间/内存使用,以及复杂性 w.r.t.限制选择的行数。再说一次,在某些关系中这不太可能是问题。
      • 我确实尝试了几种变体,考虑到特定情况的情况,这更符合我的要求。但是,我无法在默认情况下如何执行该块。我想,我对匿名关联块的使用还不足以真正理解——除了显而易见的——它们是如何工作的。不过,谢谢你的建议。
      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 2016-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多