结果集数组上的默认逻辑排序 RubyonRails

发布于 2024-08-12 15:44:04 字数 565 浏览 7 评论 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 等效的操作,但我认为这是不可能的。现在,我唯一的选择似乎是在控制器中添加一条额外的行,只是为了对此结果进行排序,但这似乎不是正确的做法。

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

I've add a custom sort to an ActiveRecord model by defining a method like this:

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

Suffice it to say, the logic actually being employed in the comparison is a bit more complex than this example, and is not something that can be accomplished with SQL.

Because this class is only used as nested fields in an encompassing model, there doesn't seem to be a straight-forward place to sort the result set. In the controller, :my_class is a part of the include for eager loading, but I don't do anything else with the object array until the view (when I do form.fields_for :my_class). What I really want is to be able to do the equivalent of default_scope using my logical sort, but I don't think that's possible. Right now, my only option seems to be adding an extra line in the controller just to do the sort on this result, but that doesn't seem like it's the right thing to do.

Is there something more elegant I'm missing here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

箜明 2024-08-19 15:44:04

执行此操作的最佳方法是设置数据库进行 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

The hands down best way to do this is to set up your database for SQL sorting and give an :order option in your scopes/finds. Doing the sort in the controller is going to be very costly once the number of objects loaded passes a certain threshold. Especially if you're trying to limit the number of records listed.

If the sort really is more complicated than sort this column than that one. You should consider adding a sort key column to the database. You've clearly worked out some method of ordering things, usually that involves comparing two values derived from the state of the object. Just store that value in the database in the new sort_key column with a before_create/save callback and order results by that.

Task Example:

Ordered by priority, but records where due date is a Friday, are listed before all others. Uses a sort_key column

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
蘸点软妹酱 2024-08-19 15:44:04

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

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

I haven't been able to test if this would work, but you could try an anonymous association module, like this:

class ParentModel < ActiveRecord::Base
  has_many :my_class do
    # Sort the result set...  
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文