Экранирование значений в Rails (аналогично mysql_real_escape_string ()) - PullRequest
33 голосов
/ 15 января 2011

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

Примерно так было бы неплохо:

self.escape("O'Malley") # O\'Malley

Ответы [ 6 ]

59 голосов
/ 17 февраля 2011

Вы можете сделать:

Dude.sanitize("O'Malley")

или

Dude.connection.quote("O'Malley")

оба с одинаковым результатом: => "'O''Malley'"

40 голосов
/ 12 февраля 2011

Быстрое погружение в источник ActiveRecord показывает его метод "sanitize_sql_array" для очистки типа оператора SQL * [string, bind_variable[, bind_variable]]

Вы можете позвонить напрямую:

sql = ActiveRecord::Base.send(:sanitize_sql_array, ["insert into foo (bar, baz) values (?, ?), (?, ?)", 'a', 'b', 'c', 'd'])
res = ActiveRecord::Base.connection.execute(sql)
22 голосов
/ 12 февраля 2011

Вы можете легко использовать драгоценный камень mysql2 для этого:

irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'mysql2'
=> true
irb(main):004:0> Mysql2::Client.escape("O'Malley") # => "O\\'Malley"
=> "O\\'Malley"

Или, если используете более ранний драгоценный камень mysql (не mysql2):

irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'mysql'
=> true
irb(main):004:0> Mysql.escape_string("O'Malley")
=> "O\\'Malley"

Это позволит вам сбежатьвсе, что вы хотите, затем вставьте в БД.Вы также можете сделать это на большинстве моделей в вашем приложении rails, используя метод sanitize.Например, скажем, у вас есть модель под названием Person.Вы могли бы сделать.

Person.sanitize("O'Malley")

Это должно сработать.

7 голосов
/ 30 октября 2012

Если вы не хотите, чтобы дополнительные одинарные кавычки, обертывающие вашу строку, возникали при использовании решения, опубликованного @konus, вы можете сделать это:

Dude.connection.quote_string("O'Malley")

Возвращается "O\'Malley" вместо "'O\'Malley'"

4 голосов
/ 15 января 2011

Даже с Model.find_by_sql вы все равно можете использовать форму, в которой знаки вопроса стоят как экранированные значения.

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

Пример из документации по Rails API:

Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
2 голосов
/ 04 ноября 2011

На случай, если кто-то ищет более конкретный пример решения @ jemminger, он предназначен для массовой вставки:

users_places = []
users_values = []
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
params[:users].each do |user|
    users_places "(?,?,?,?)"
    users_values << user[:name] << user[:punch_line] << timestamp << timestamp
end

bulk_insert_users_sql_arr = ["INSERT INTO users (name, punch_line, created_at, updated_at) VALUES #{users_places.join(", ")}"] + users_values
begin
    sql = ActiveRecord::Base.send(:sanitize_sql_array, bulk_insert_users_sql_arr)
    ActiveRecord::Base.connection.execute(sql)
rescue
    "something went wrong with the bulk insert sql query"
end

Вот ссылка на метод sanitize_sql_array в ActiveRecord :: Base , он генерирует правильную строку запроса, экранируя одинарные кавычки в строках.Например, punch_line «Не позволяйте им вас унизить» станет «Не позволяйте им вас унизить».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...