2011-01-14 23 views

Respuesta

53

que puede hacer:

Dude.sanitize("O'Malley") 

o

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

ambos con el mismo resultado: => "'O''Malley'"

+3

Me encanta tu nombre de modelo. 'Amigo ', eres increíble. –

+6

@NateSymer: Sí, bueno, así es, como, tu opinión, hombre. – Fuser97381

+2

En caso de que alguien más se esté preguntando, sí, son exactamente lo mismo: [desinfectar llamadas connection.quote] (http://apidock.com/rails/ActiveRecord/Base/sanitize/class) – mltsy

4

Incluso con Model.find_by_sql todavía se puede utilizar la forma en que se interponen en signos de interrogación como valores escapado.

Basta con pasar una matriz en donde el primer elemento es la consulta y elementos sucesivos son los valores que ser sustituido en

Ejemplo de la documentación de Rails API:.

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

¿Qué pasa si estoy insertando? –

+1

Puedo desenterrarlo, pero realmente: ¿por qué estás insertando fuera de ActiveRelation/ActiveModel? –

+1

Estoy haciendo un 'INSERT IGNORE' y estoy actualizando varios registros en una declaración para el rendimiento. –

19

Usted puede utilizar fácilmente el mysql2 gema para hacer esto:

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" 

O si se utiliza el MySQL anterior (no mysql2) joya:

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" 

Esto le permitirá escapar de todo lo que desee y luego insertarlo en la base de datos. También puede hacer esto en la mayoría de los modelos en su aplicación de rieles utilizando el método de sanitización. Por ejemplo decir que tienes un modelo llamado Persona. Podrías hacerlo.

Person.sanitize("O'Malley") 

Eso debería hacer el truco.

+0

Extraño ... esta fue la respuesta promovida ... luego fue cambiada ... arg. – quest

+10

Con la gema Mysql2: 'Mysql2 :: Client.escape (" O'Malley ") # =>" O \\ 'Malley "' – Duke

31

Una inmersión rápida en la fuente de ActiveRecord revela su método "sanitize_sql_array" para la desinfección del tipo de instrucción SQL [string, bind_variable[, bind_variable]]

Se le podría llamar directamente:

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

Jason: Esta es una solución mejor ya que es independiente de DB. Si la aplicación se implementa en Heroku, la solución actualmente aceptada (@quest) no funcionará. –

+7

Cuatro años después, 'sanitize_sql_array' y sus primos aún no son parte de la API pública. ¿Hay un equivalente público conveniente? –

2

En caso de que alguien está buscando a un ejemplo más concreto de la solución de @ jemminger, aquí está para inserción masiva:

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 

Aquí es el reference to sanitize_sql_array method in ActiveRecord::Base, genera la cadena de consulta adecuada escapando las comillas simples en las cadenas. Por ejemplo, punch_line "No dejes que te depriman" se convertirá en "No dejes que te depriman".

7

Si no desea que las cotizaciones adicionales individuales envolviendo su cadena que se produce al utilizar la solución Publicado por @konus, usted puede hacer esto:

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

Esto devuelve "O\'Malley" en lugar de "'O\'Malley'"

+1

Esto no le impedirá SQL inyección. – tvdeyen

+2

@tvdeyen: ¿Estaría dispuesto a ilustrar de qué manera lo anterior sería vulnerable, especialmente en comparación con la respuesta aceptada? En definitiva, 'quote_string' dependerá del adaptador ActiveRecord particular que se utilice. Para el adaptador mysql2 y el adaptador mysql abstracto, 'quote' llama a' quote_string' para valores de cadenas y ajusta el resultado entre comillas. ¿Estás pensando en algún tipo de inyección multibyte o algo más? Gracias. – Nathan

+0

Gracias @Nathan., Funciona para mí .. –