如何消毒 Arel SQL?
How to sanitize Arel SQL?
我有以下 Arel SQL:
Arel.sql("(users.last_donated_at IS NOT NULL AND users.last_donated_at < '#{User::ACTIVE_DONOR_WITHIN_DAYS.days.ago}')")
当我 运行 brakeman 时,我收到 SQL Injection
警告。我尝试了以下方法:
Arel.sql("(users.last_donated_at IS NOT NULL AND users.last_donated_at < ?)", User::ACTIVE_DONOR_WITHIN_DAYS.days.ago)
但是,我收到以下错误:
ArgumentError:
wrong number of arguments (given 2, expected 1)
如何使用 Arel 清理 sql 语句?
使用 Arel.sql
通常不是处理查询的最佳方式。在我看来,您不需要清理此查询,您需要对其进行重构。
您可以在 Arel
中使用便捷方法 rails where 子句(以及大多数其他查询方法 order
、select
等)构建条件 ModelName.arel_attribute(:attribute_name)
这将允许您构建超出 rails' native where Hash
.
提供的高级支持的查询条件
这与
相同
table_name = ModelName.arel_table
table_name[:attribute_name]
所以让我们将其应用到您的查询中:
根据您的查询,IS NOT NULL 条件没有任何意义,因为您也使用了小于,因此我们可以将条件更改为仅使用小于,例如
User.arel_attribute(:last_donated_at).lt(User::ACTIVE_DONOR_WITHIN_DAYS.days.ago)
这是可行的,因为 NULL 不小于(或大于,甚至等于)任何值,所以这些结果不会以任何一种方式显示。
如果您坚持 IS NOT NULL 条件,我们仍然可以通过以下方式使用 Arel Atributes 生成所需的 SQL:
User.arel_attribute(:last_donated_at).not_eq(nil).and(
User.arel_attribute(:last_donated_at).lt(User::ACTIVE_DONOR_WITHIN_DAYS.days.ago)
)
我正在回答我自己的问题。我在 Github wiki 之后使用 Arel for Ransack gem。我正在做的事情与文档中提到的第 # 2.2 点非常相似:https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers。
为了清理参数并避免 brakeman sql injection
警告,我最终执行了以下操作:
Arel.sql(sanitize_sql_array("(users.last_donated_at IS NOT NULL AND users.last_donated_at < '#{User::ACTIVE_DONOR_WITHIN_DAYS.days.ago}')"))
我有以下 Arel SQL:
Arel.sql("(users.last_donated_at IS NOT NULL AND users.last_donated_at < '#{User::ACTIVE_DONOR_WITHIN_DAYS.days.ago}')")
当我 运行 brakeman 时,我收到 SQL Injection
警告。我尝试了以下方法:
Arel.sql("(users.last_donated_at IS NOT NULL AND users.last_donated_at < ?)", User::ACTIVE_DONOR_WITHIN_DAYS.days.ago)
但是,我收到以下错误:
ArgumentError:
wrong number of arguments (given 2, expected 1)
如何使用 Arel 清理 sql 语句?
使用 Arel.sql
通常不是处理查询的最佳方式。在我看来,您不需要清理此查询,您需要对其进行重构。
您可以在 Arel
中使用便捷方法 rails where 子句(以及大多数其他查询方法 order
、select
等)构建条件 ModelName.arel_attribute(:attribute_name)
这将允许您构建超出 rails' native where Hash
.
这与
相同table_name = ModelName.arel_table
table_name[:attribute_name]
所以让我们将其应用到您的查询中:
根据您的查询,IS NOT NULL 条件没有任何意义,因为您也使用了小于,因此我们可以将条件更改为仅使用小于,例如
User.arel_attribute(:last_donated_at).lt(User::ACTIVE_DONOR_WITHIN_DAYS.days.ago)
这是可行的,因为 NULL 不小于(或大于,甚至等于)任何值,所以这些结果不会以任何一种方式显示。
如果您坚持 IS NOT NULL 条件,我们仍然可以通过以下方式使用 Arel Atributes 生成所需的 SQL:
User.arel_attribute(:last_donated_at).not_eq(nil).and(
User.arel_attribute(:last_donated_at).lt(User::ACTIVE_DONOR_WITHIN_DAYS.days.ago)
)
我正在回答我自己的问题。我在 Github wiki 之后使用 Arel for Ransack gem。我正在做的事情与文档中提到的第 # 2.2 点非常相似:https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers。
为了清理参数并避免 brakeman sql injection
警告,我最终执行了以下操作:
Arel.sql(sanitize_sql_array("(users.last_donated_at IS NOT NULL AND users.last_donated_at < '#{User::ACTIVE_DONOR_WITHIN_DAYS.days.ago}')"))