Подтвердить что ты не робот

Экранирование значений в Rails (аналогично mysql_real_escape_string())

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

Что-то вроде этого было бы хорошо:

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

Ответ 1

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

Dude.sanitize("O'Malley")

или

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

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

Ответ 2

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

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

sql = ActiveRecord::Base.send(:sanitize_sql_array, ["insert into foo (bar, baz) values (?, ?), (?, ?)", 'a', 'b', 'c', 'd'])
res = ActiveRecord::Base.connection.execute(sql)

Ответ 3

Вы можете легко использовать камень 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) gem:

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"

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

Person.sanitize("O'Malley")

Это должно сделать трюк.

Ответ 4

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

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

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

Ответ 5

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

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

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

Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]

Ответ 6

Если кто-то ищет более конкретный пример решения @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 "Не позволяйте им сбивать вас" станет "Не позволяйте им сбивать вас".