1

У меня есть объект с кучей атрибутов, представляющих атрибуты модели с возможностью поиска, и я хотел бы динамически создавать SQL-запрос, используя только те атрибуты, которые установлены. Я создал метод ниже, но я считаю, что он восприимчив к атакам SQL-инъекций. Я провел некоторое исследование и прочитал руководство по интерфейсу активных запросов рельсов, но похоже, что для условия всегда требуется статически определенная строка в качестве первого параметра. Я также попытался найти способ дезинфекции строки sql, созданной моим методом, но похоже, что есть хороший способ сделать это.rails dynamic, где 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 

ответ

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 

Те предполагают, что вы правильно белый список все переменные экземпляра. Если у вас нет, тогда вам нужно.

+0

Ничего себе, я поражен твоими навыками Руби. Второй пример - взрывное взрывное устройство. Благодаря! –