Ruby on Rails: как санировать строку для SQL, когда не используется find? - PullRequest
12 голосов
/ 23 марта 2010

Я пытаюсь санировать строку, которая включает ввод данных пользователем, не прибегая к ручному созданию собственного, возможно, ошибочного регулярного выражения, если это возможно, однако, если это единственный способ, я также был бы признателен, если бы кто-то мог указать мне правильное направление к регулярному выражению, которое вряд ли что-то упустит. В Rails есть ряд методов, которые позволяют вам вводить собственные команды SQL. Как люди избегают ввода данных пользователем?

Вопрос, который я задаю, является широким, но в моем конкретном случае я работаю со столбцом в моей базе данных Postgres, который Rails не понимает изначально, насколько я знаю, с tsvector, который содержит простой текст поиск информации. Rails может писать и читать из нее, как если бы это была строка, однако, в отличие от строки, она, кажется, не автоматически выходит из нее, когда я делаю что-то вроде vector = внутри модели.

Например, когда я делаю model.name = '::', где name это строка, она работает нормально. Когда я делаю model.vector = '::', это выдает ошибку:

ActiveRecord::StatementInvalid: PGError: ERROR:  syntax error in tsvector: "::"
"vectors" = E'::' WHERE "id" = 1

Кажется, это проблема, вызванная отсутствием точек с запятой, и я могу вручную установить vector = '::' fine.

У меня тоже была блестящая идея, может быть, я могу просто назвать что-то вроде:

ActiveRecord::Base.connection.execute "UPDATE medias SET vectors = ? WHERE id = 1", "::"

Однако этот синтаксис не работает, поскольку необработанные команды SQL не имеют доступа к методу экранирования и ввода строк find с использованием символа? знак.

Это вызывает у меня ту же проблему, что и вызов connection.execute с любым типом пользовательского ввода, поскольку все сводится к очистке строк, но я не могу найти какой-либо способ вручную вызвать очистку строк в SQL Rails вручную методы. Кто-нибудь может дать какой-нибудь совет?

1 Ответ

15 голосов
/ 23 марта 2010

Добавьте этот метод к вашей модели:

class Media < ActiveRecord::Base
  def self.execute_sql(*sql_array)     
    connection.execute(send(:sanitize_sql_array, sql_array))
  end
end

Теперь вы можете выполнить любой SQL, например:

Media.execute_sql('UPDATE medias SET vectors = ? WHERE id = 1', '::')

Ссылка

1) sanitize_sql_array

...