【问题标题】:rails dynamic where sql queryrails 动态 where sql 查询
【发布时间】:2016-10-09 02:40:49
【问题描述】:

我有一个带有一堆属性的对象,这些属性代表可搜索的模型属性,我想只使用设置的属性动态创建一个 sql 查询。我创建了下面的方法,但我相信它容易受到 sql 注入攻击。我做了一些研究并阅读了rails活动记录查询界面指南,但似乎where条件总是需要一个静态定义的字符串作为第一个参数。我还试图找到一种方法来清理我的方法生成的 sql 字符串,但似乎也没有一个好的方法可以做到这一点。

我怎样才能做得更好?我应该使用 where 条件还是只是以某种方式清理这个 sql 字符串?谢谢。

def query_string
  to_return = ""

  self.instance_values.symbolize_keys.each do |attr_name, attr_value|
    if defined?(attr_value) and !attr_value.blank?
      to_return << "#{attr_name} LIKE '%#{attr_value}%' and "
    end
  end
  to_return.chomp(" and ")
end

【问题讨论】:

    标签: ruby-on-rails postgresql rails-activerecord ruby-on-rails-5


    【解决方案1】:

    您的方法有点偏离,因为您试图解决错误的问题。您正在尝试构建一个字符串以传递给 ActiveRecord,以便在您应该只是尝试构建查询时它可以构建查询。

    当你说这样的话:

    Model.where('a and b')
    

    这和说的一样:

    Model.where('a').where('b')
    

    你可以说:

    Model.where('c like ?', pattern)
    

    代替:

    Model.where("c like '#{pattern}'")
    

    将这两个想法与您的 self.instance_values 结合起来,您可以得到如下结果:

    def query
      self.instance_values.select { |_, v| v.present? }.inject(YourModel) do |q, (name, value)|
        q.where("#{name} like ?", "%#{value}%")
      end
    end
    

    甚至:

    def query
      empties      = ->(_, v) { v.blank? }
      add_to_query = ->(q, (n, v)) { q.where("#{n} like ?", "%#{v}%") }
      instance_values.reject(&empties)
                     .inject(YourModel, &add_to_query)
    end
    

    这些假设您已将所有实例变量正确列入白名单。如果你还没有,那么你应该这样做。

    【讨论】:

    • 哇,我对你的 Ruby 技能感到敬畏。第二个例子是头脑风暴。谢谢!
    猜你喜欢
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 2014-08-04
    • 2020-10-02
    • 1970-01-01
    相关资源
    最近更新 更多