如何在 Rails 中使用 LIKE 查询枚举?

问题描述 投票:0回答:3

我已将枚举 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... ^ 提示:没有运算符与给定名称和参数类型匹配。你可能需要 添加显式类型转换。

有什么建议吗?

ruby-on-rails ruby plpgsql pg-search
3个回答
3
投票

枚举通常作为整数存储在数据库中。到标签的映射是在应用程序级别完成的。数据库不知道标签。

这意味着您必须弄清楚哪些标签符合您的应用程序级别标准。然后将它们转换为整数值(在数据库中使用)。实现此目的的一种方法是将

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)
的符号。


3
投票

如果你想在这里使用枚举,那么你需要将枚举值作为字符串存储在数据库中。目前您的列

task_status
具有
integer
类型。因此你不能使用 LIKE 运算符进行搜索。要解决此问题,请进行此更改。

  enum task_status: {pending: 'pending', complete: 'complete'}

并将

task_status
列的类型设置为 db 中的
string
。 但我建议您如果可能的话从前端发送值的全名。


0
投票

我最终修改了3limin4t0r的答案

scope :search_status, lambda { |status|
  where(status: statuses.keys.select { |i| i.include?(status.downcase) })
}

因为我不确定

.grep
针对用户输入的安全性。

© www.soinside.com 2019 - 2024. All rights reserved.