弃用警告:使用非属性参数调用的危险查询方法(其参数用作原始SQL的方法)

时间:2018-04-17 21:14:36

标签: ruby-on-rails ruby ruby-on-rails-5.2

我将rails 5.1.4 app更新为5.2.0。我的一个模型中有以下范围:

  scope :by_category, lambda { |category_slug|
    category_ids = Category.find_by(slug: category_slug)&.subtree_ids
    where(category_id: category_ids)
  }

由于该范围,Rails返回错误:

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "coalesce(\"categories\".\"ancestry\", '')". 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()

我该如何解决?

1 个答案:

答案 0 :(得分:7)

问题在于ordered_by_ancestry scope

scope :ordered_by_ancestry, Proc.new { |order|
  if %w(mysql mysql2 sqlite sqlite3 postgresql).include?(connection.adapter_name.downcase) && ActiveRecord::VERSION::MAJOR >= 5
    reorder("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, '')", order)
  else
    reorder("(CASE WHEN #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)} IS NULL THEN 0 ELSE 1 END), #{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}", order)
  end
}

将SQL的原始字符串传递给#reorder,并且如警告所述,这在Rails 5.2中已弃用(并将在Rails 6中完全删除)。

刚刚提交了pull request,通过在Arel.sql次调用中包装这些字符串来解决此问题。我希望这会快速合并(尽管拉请求在第二个分支中缺少Arel.sql调用)但同时你有一些选择:

  1. 忽略警告并等待修补宝石。

  2. 分叉gem,合并pull请求,并使用你的分叉版本,直到gem合并有问题的pull请求。

  3. 手动替换ordered_by_ancestry范围:

    def self.ordered_by_ancestry(order)
      reorder(Arel.sql("coalesce(#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(ancestry_column)}, '')"), order)
    end
    

    并等待拉取请求合并。

  4. 更新:解决此警告的拉取请求为just merged,因此无需再等待,您应该能够从GitHub获取最新信息并继续处理更多有趣的事情。感谢kbrock对此进行排序。