弃用警告:危险的查询方法(其参数用作原始 SQL 的方法)。如何包裹在 Arel 中?

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL). How to wrap in Arel?

我有这个查询:

@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 中?

根据弃用,您可以按如下方式包装:

.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 as long as it follows standard column_name or table.column_name syntax Whitelist can be found here and as always Arel objects will also be supported Reference