优先级警告:危险的查询方法(其参数用作原始SQL的方法)。如何包装Arel?

时间:2019-07-25 20:15:42

标签: ruby-on-rails ruby activerecord ruby-on-rails-6

我有这个查询:

@members = Member.where("EXTRACT(DOY FROM date_of_birth) >= ?", next_bdays).order('EXTRACT (DOY FROM date_of_birth) ASC').first(5)

出现错误:

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "EXTRACT (DOY FROM (Arel.sql \"DATE(date_of_birth)\")) ASC". Non-attribute arguments will be disallowed in Rails 6.0. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql().

该怎么办?如何将date_of_birth包装在Arel中?

1 个答案:

答案 0 :(得分:2)

根据DEPRECATION,您可以将其包装如下:

.order(Arel.sql('EXTRACT (DOY FROM date_of_birth) ASC'))

甚至

.order(Arel.sql('EXTRACT (DOY FROM date_of_birth)').asc)

但是我将更进一步,并遵循以下要求:

custom_clause = Arel::Nodes::NamedFunction.new('EXTRACT',
  [Arel::Nodes::SqlLiteral.new("DOY FROM members.date_of_birth")]
)

这将产生所需的SQL,并且可以像where子句一样重复使用

@members = Member
            .where(custom_clause.gteq(next_bdays))
            .order(Arel.sql(custom_clause.to_sql).asc)
            .first(5)

这将产生以下查询。 (假设next_bdays == 123

SELECT 
  members.* 
FROM 
  members 
WHERE 
  EXTRACT(DOY FROM members.date_of_birth) >= 123  
ORDER BY 
  EXTRACT(DOY FROM members.date_of_birth) ASC
LIMIT 5

Some Raw SQL will be acceptable,只要它遵循标准的column_name或table.column_name语法Whitelist can be found here,并且一如既往,也将支持Arel对象Reference