Rails 已审核的搜索

Rails audited search

我正在尝试查找去年设置为特定状态的所有项目。 我正在使用经过审核的 Rail 5,因此我创建了一个特定的审核模型,并尝试将范围写入 return 我的条件:

Audit = Audited.audit_class

class Audit
  scope :followupRebus, -> { where(auditable_type: 'Followup')
    .where(action: 'update')
    .where("audited_changes LIKE '%step_id:[#{Step::REBUS}%'")
  }

end

postgres 中经过审核的文本字段的内容看起来像这样,当我拿它并用 .to_s

显示它时
{"step_id"=>[9, 4], "active"=>[false, true]}

如何通过 step_id = 9 获得所有审核?

编辑

非常感谢 DRSE,我终于找到了一个可行的解决方案:

  1. 使用 DRSE 发送的迁移更改列的默认文本类型
  2. 像这样更改请求:

    class 审核 范围:followupRebus,-> { 其中(auditable_type:'Followup') .where(动作:'update') .where("((audited_changes -> 'step_id')::json->>0::int = :step_id", step_id: Step::REBUS) }

    结束

您需要使用 Postgres JSON functions 来查询 JSON 列 audited_changes 而不是 LIKE 运算符。

要查找 step_id 更改的审计,您可以使用

.where("(audited_changes -> 'step_id')::jsonb ? :step_id", step_id: '9')

注意 named bind variable :step_id 的使用,而不是使用活动记录问号 (?) 替换,因为 Postgres 使用问号作为 JSON 查询运算符。

以上子句将查找 step_id = 9 处的任何审核,无论该值是在先前版本中设置的值还是模型的更新版本。

要查找以前版本中 step_id = 9 的审计:

# Check if the first value (indexed by 0) in 'step_id' array is '9'
.where("(audited_changes -> 'step_id')::jsonb->0 ? :step_id", step_id: '9')

要在更新版本中查找 step_id = 9 设置的审核:

# Check if the second value (indexed by 1) in 'step_id' array is 9
.where("(audited_changes -> 'step_id')::jsonb->1 ? :step_id", step_id: '9')

(注意:您不应该直接对 where 子句的条件进行字符串插入,因为您正在将应用程序打开到 SQL injection vulnerability. Use rails style conditions with sanitized inputs。)

编辑

由于您已指出您的 audited_changes 列类型是 TEXT 而不是 JSON 类型,您将需要 运行 迁移以更改列类型或强制转换查询中的列。

要在查询执行时将列转换为 JSON,请使用 audited_changes::json,因此示例如下:

.where("(audited_changes::json -> 'step_id')::json ? :step_id", step_id: '9')

要将列更改为 JSON,请从 rails g migration ChangeAuditedChangesColumnToJSONB 开始。然后在您的迁移文件 (db/migrate/{timestamp}_change_audited_changes_column_to_jsonb.rb) 中写入:

class ChangeAuditedChangesColumnToJSONB < ActiveRecord::Migration[5.1]
  def up
    change_column :audits, :audited_changes, :jsonb, using: 'audited_changes::JSONB'
  end

  def down
    change_column :audits, :audited_changes, :text
  end
end

然后 运行 rails db:migrate 就可以开始了。

对于使用 Audited 的新项目,您可以add a param to the install step为 audited_changes 列指定使用 JSON 或 JSONB 类型。

rails generate audited:install --audited-changes-column-type jsonb # or json