0

我有这个查询:

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

4

1 回答 1

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

一些原始 SQL只要遵循标准 column_name 或 table.column_name 语法就可以接受白名单可以在这里找到,并且一如既往地支持 Arel 对象参考

于 2019-07-25T20:36:00.893 回答