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 t开发者_如何学Pythonhink 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?
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
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
精彩评论