ruby或rails是否提供了按指定顺序排序字符串的方法?假设我有以下优先级"严重,高,中,低".
这些优先事项不会经常变化(如果有的话).我有一个优先级列的任务模型:
tasks
- id (integer)
- name (string)
- priority (string)
Run Code Online (Sandbox Code Playgroud)
我想获得按优先级排序的所有任务的数组.由于逻辑顺序不遵循字母顺序,因此无法按优先级顺序排序:
Task.all(:order => :priority)
Run Code Online (Sandbox Code Playgroud)
我所做的是创建优先级模型并定义关联:任务belongs_to优先级.在优先级表中,然后我为每个优先级名称分配了一个值并按该值排序.有一个更好的方法吗?我宁愿没有优先级表并声明PRIORITY常量(作为哈希),或者只是在task表中将优先级指定为字符串.
Evi*_*out 26
您可以在where子句中使用case语句.这有点难看,但应该工作:
class Task
PRIORITIES_ORDERED = ['high', 'medium', 'low']
# Returns a case statement for ordering by a particular set of strings
# Note that the SQL is built by hand and therefore injection is possible,
# however since we're declaring the priorities in a constant above it's
# safe.
def self.order_by_case
ret = "CASE"
PRIORITIES_ORDERED.each_with_index do |p, i|
ret << " WHEN priority = '#{p}' THEN #{i}"
end
ret << " END"
end
named_scope :by_priority, :order => order_by_case
end
Run Code Online (Sandbox Code Playgroud)
然后,当您希望按优先级排序时,您可以执行以下操作:
Task.all.by_priority
Run Code Online (Sandbox Code Playgroud)
当然,正如其他人所提到的,为Priority表而不是文本字符串列创建外键更为清晰.在Priorty表中,您可以将位置列添加为可以排序的整数,并且存在插件以使其更容易.
tma*_*314 13
这是更新版本,适用于rails 4.1和一些自定义:
PRIORITIES_ORDERED = ['Unknown', 'Critical', 'Warning', 'Ok']
def self.order_by_case
ret = "CASE"
PRIORITIES_ORDERED.each_with_index do |p, i|
ret << " WHEN status = '#{p}' THEN #{i}"
end
ret << " END"
end
scope :order_by_priority, -> { order(order_by_case) }
Run Code Online (Sandbox Code Playgroud)
这是 Rails 7 的更新版本:
Task.in_order_of(:priority, %w[Severe High Medium Low])
Run Code Online (Sandbox Code Playgroud)
像 Aaron 所说的那样切换到整数,那么您可能会想要使用default_scope。
例如:
class Task < ActiveRecord::Base
default_scope :order => 'tasks.position' # assuming the column name is position
...
Run Code Online (Sandbox Code Playgroud)
使用默认范围,您不必在任何查找方法调用中指定排序顺序 - 任务将自动排序。