我已将枚举 task_status 设置为:
class ConfirmedTask < ApplicationRecord
enum task_status: {pending: 1, complete: 2}
end
现在我必须使用搜索参数“pend”搜索所有处于待处理状态的任务。我正在使用 pg_search 进行搜索,但它不适用于枚举,所以我想使用 LIKE 查询进行查询:
ConfirmedTask.where('task_status like ?', '%pend%')
但这给了我错误
ActiveRecord::StatementInvalid (PG::UndefinedFunction: 错误: 运算符不存在:整数 ~~ 未知)第 1 行:...询问".* FROM “confirmed_tasks” WHERE(任务状态如 '%pen... ^ 提示:没有运算符与给定名称和参数类型匹配。你可能需要 添加显式类型转换。
有什么建议吗?
枚举通常作为整数存储在数据库中。到标签的映射是在应用程序级别完成的。数据库不知道标签。
这意味着您必须弄清楚哪些标签符合您的应用程序级别标准。然后将它们转换为整数值(在数据库中使用)。实现此目的的一种方法是将
grep
与符合您要求的 regex 结合使用。
# find the matching labels
labels = ConfirmedTask.task_statuses.keys.grep(/pend/i)
# convert them into their integer values
values = labels.map(&ConfirmedTask.task_statuses)
# create your query
ConfirmedTask.where('task_status IN (?)', values)
更简单的方法是把标签放到值翻译上,然后让 Rails 来解决这个问题。这可以通过将标签数组传递给正常的
where
调用(使用非 SQL 字符串参数)来完成。
# find the matching labels
labels = ConfirmedTask.task_statuses.keys.grep(/pend/i)
# pass labels to `where` and let Rails do the label -> integer conversion
ConfirmedTask.where(task_status: labels)
我不能 100% 确定是否允许字符串数组作为枚举属性的
where
条件。 文档使用符号。如果上述方法不起作用,请将字符串映射为带有 .map(&:to_sym)
的符号。
如果你想在这里使用枚举,那么你需要将枚举值作为字符串存储在数据库中。目前您的列
task_status
具有 integer
类型。因此你不能使用 LIKE 运算符进行搜索。要解决此问题,请进行此更改。
enum task_status: {pending: 'pending', complete: 'complete'}
并将
task_status
列的类型设置为 db 中的 string
。
但我建议您如果可能的话从前端发送值的全名。
我最终修改了3limin4t0r的答案
scope :search_status, lambda { |status|
where(status: statuses.keys.select { |i| i.include?(status.downcase) })
}
因为我不确定
.grep
针对用户输入的安全性。