首页 > 解决方案 > 你将如何在 Ruby 中替换这个 SQL 查询,以便只使用 ActiveRecord 代码?

问题描述

这实际上是有效的(它返回数据库中曲目数量最多的 5 位艺术家)

def top_five_artists(genre_name)
  # TODO: return the 5 artists with the more tracks of genre `genre_name`
  Artist.joins(albums: { tracks: :genre }).where(genres: { name: genre_name }).group(:name).order("COUNT(*) DESC").limit(5)
end

但会引发以下警告:

弃用警告:使用非属性参数调用的危险查询方法(其参数用作原始 SQL 的方法):“COUNT(*) DESC”。Rails 6.1 将不允许使用非属性参数。不应使用用户提供的值(例如请求参数或模型属性)调用此方法。可以通过将已知安全值包装在 Arel.sql() 中来传递它们。(从 /home/maxichalbaud/code/maxichalbaud/fullstack-challenges/03-AR-Database/03-ActiveRecord-Basics/Optional-01-Mapping-Existing-Database/app/queries.rb:18 的 top_five_artists 调用)

您将如何重构“COUNT(*) DESC”行?

标签: sqlrubyactiverecord

解决方案


你可以试试这个:

def top_five_artists(genre_name)
  Artist.joins(albums: { tracks: :genre })
        .where(genres: { name: genre_name })
        .group(:name)
        .order(Arel.sql('count(*) DESC'))
        .limit(5)
end

首先,您可以使用上面提到的mu_is_too_shortorder(Arel.sql('count(*) DESC'))来摆脱弃用警告,然后,您可以将代码编写成多行,这样 RuboCop 就不会因为“这行太长”而困扰您。


推荐阅读