我正在使用MySQL并将我的应用程序升级到Rails 7。在这样做的过程中,我必须重构我的范围方法中的一些与订单相关的查询。
在Rails 7之前,我使用了以下范围方法(称之为“原始范围方法”):
scope.order(sanitize_sql_array(["CASE articles.author_id WHEN ? THEN 1 ELSE 2 END", author.id]))
在Rails 7中,上面的语句会引发错误:
ActiveRecord::UnknownAttributeReference(使用非属性参数调用的危险查询方法(其参数用作原始SQL的方法):“CASEarticles.author_id WHEN '3784' THEN 1 ELSE 2 END”。不应使用用户提供的值(如请求参数或模型属性)调用此方法。可以通过将已知安全的值 Package 在Arel.sql()中来传递这些值。):
在这些情况下,Rails 7中可能会派上用场的是新添加的方法in_order_of
。因此,原始的scope方法可能会变成:
scope.in_order_of(:author_id, [author.id])
然而,这个in_order_of
方法向SQL查询添加了一个(unwanted)WHERE子句,即以下查询中的“AND 'articles'.'author_id'”部分:
SELECT `articles`.* FROM `articles`
WHERE (articles.some_other_column >= 10) AND `articles`.`author_id` IN (3784)
ORDER BY FIELD(`articles`.`author_id`, 3784) DESC
额外的WHERE子句的(unwanted)效果是从查询结果中删除了所有记录,这些记录是在我使用Rails 7之前的原始范围方法时出现的,即在上面的示例中,除了3784之外的作者ID被忽略,但应该出现在查询结果中。
我如何在Rails 7中构建/重构与原始的“CASE-WHEN-THEN-ELSE-END”等效的范围方法,我在Rails 7之前使用它来根据给定的作者ID对记录进行排序?
2条答案
按热度按时间s4n0splo1#
使用Arel调用任何函数都很容易:
Arel::Nodes::NamedFunction.new
接受一个函数名和一个参数数组。9avjhtql2#
通过按照错误消息中的建议在Arel.sql()中 Package 属性(已知安全的值)找到了解决方案。
因此SQL查询将是: