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,我终于找到了一个可行的解决方案:
- 使用 DRSE 发送的迁移更改列的默认文本类型
像这样更改请求:
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
我正在尝试查找去年设置为特定状态的所有项目。 我正在使用经过审核的 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,我终于找到了一个可行的解决方案:
- 使用 DRSE 发送的迁移更改列的默认文本类型
像这样更改请求:
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