【问题标题】:How can I sort ActiveRecord Objects by id array如何按 id 数组对 ActiveRecord 对象进行排序
【发布时间】:2013-05-28 16:20:38
【问题描述】:

我的环境

ruby 2.0.0-p195
rails (4.0.0.rc1)
activerecord (4.0.0.rc1)

我想按 id 数组对 ActiveRecord 对象进行排序。 我试过按字段排序。

ids = [1,4,2,3]
Foo.where(id: ids).order('FIELD(id, ?)', ids)

但是失败了。

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?,?,?,?}), ö, ÷, ï, ñ' at line 1:

那我试试

ids = [1,4,2,3]
Foo.where(id: ids).order('FIELD(id, #{ids.join(","))')

这当然是成功的。但是我担心它可能存在 SQL 注入风险,因为数组 id 是从会话值生成的。

有没有更好更安全的方法?

提前致谢。

【问题讨论】:

  • a 中存储了什么?我想您可能正在寻找Foo.where(id: ids).order('id ASC')。在Rails Guides on the ActiveRecord Query Interface 中查看有关查询和排序的所有信息。
  • 感谢您的评论。 “a”是“ids”的错误。我编辑了错误。那么我想做的不是“ORDER BY id ASC”而是“ORDER BY FIELD(id, 1, 4, 2, 3)”。

标签: ruby-on-rails ruby-on-rails-4 mysql2


【解决方案1】:

你是对的,这是一个安全漏洞。

我看到了两种可能性:

转换为数字

ids = [1,4,2,3].map(&:to_i).compact
Foo.where(id: ids).order("FIELD(id, #{ids.join(',')})")

我认为这应该是安全的,因为您确保值是数字,然后删除 nil 条目。 nil 条目将是非数字条目。

转义字符串

escaped_ids = ActiveRecord::Base::sanitize(ids.join(","))
Foo.where(id: ids).order("FIELD(id, #{escaped_ids})")

你只是逃避你的字符串的内容......没什么特别的。

【讨论】:

    【解决方案2】:

    我在 Rails6 上使用 FIELD 方法尝试了这个答案,但遇到了错误。但是,我发现只需将 sql 包装在 Arel.sql() 中即可。

    # Make sure it's a known-safe values.
    user_ids = [3, 2, 1]
    # Before 
    users = User.where(id: user_ids).order("FIELD(id, 2, 3, 1)")
    # With warning.
    
    # After 
    users = User.where(id: user_ids).order(Arel.sql("FIELD(id, 2, 3, 1)"))
    # No warning
    

    [1]https://medium.com/@mitsun.chieh/activerecord-relation-with-raw-sql-argument-returns-a-warning-exception-raising-8999f1b9898a

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-17
      • 2017-04-27
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-11
      • 2010-11-28
      相关资源
      最近更新 更多