0

我试图找到去年设置为特定状态的所有项目。我正在使用经过审计的 Rail 5,所以我创建了一个特定的审计模型,并尝试编写一个范围来返回我的条件:

Audit = Audited.audit_class

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

end

当我拿走它并用.to_s

{"step_id"=>[9, 4], "active"=>[false, true]}

我怎样才能获得所有审计step_id = 9

编辑

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

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

    类审计范围 :followupRebus, -> { where(auditable_type: 'Followup') .where(action: 'update') .where("((audited_changes -> 'step_id')::json->>0)::int = :step_id", step_id: Step::REBUS) }

    结尾

4

1 回答 1

4

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

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

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

注意使用命名绑定变量 :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要在更新版本中查找带有 set 的审计:

# 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 注入漏洞。请改用带有经过清理的输入的 rails 样式条件。)

编辑

由于您已指示您的 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 的新项目,您可以在安装步骤中添加一个参数,以指定对 audited_changes 列使用 JSON 或 JSONB 类型。

rails generate audited:install --audited-changes-column-type jsonb # or json
于 2017-08-14T14:50:54.800 回答