2011-01-14 9 views

risposta

53

si può fare:

Dude.sanitize("O'Malley") 

o

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

entrambi con lo stesso risultato: => "'O''Malley'"

+3

Amo il nome del tuo modello. "Amico", sei fantastico. –

+6

@NateSymer: Sì, beh, è ​​solo una tua opinione, amico. – Fuser97381

+2

Nel caso in cui qualcun altro si stia chiedendo, sì, sono esattamente gli stessi: [sanitize chiama connection.quote] (http://apidock.com/rails/ActiveRecord/Base/sanitize/class) – mltsy

4

Anche con Model.find_by_sql è ancora possibile utilizzare il modulo in cui punti interrogativi stanno in come valori sfuggiti.

semplicemente passare un array in cui il primo elemento è la query e elementi successivi sono i valori da sostituiti in

Esempio dalla documentazione Rails API:.

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

Cosa succede se sto inserendo? –

+1

Posso scoprirlo, ma davvero: perché stai inserendo all'esterno ActiveRelation/ActiveModel? –

+1

Sto facendo un 'INSERT IGNORE' e sto aggiornando più record in una dichiarazione per le prestazioni. –

19

Si può facilmente utilizzare l'mysql2 gemma per fare questo:

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" 

Oppure, se si utilizza il mysql in precedenza (non mysql2) gemma:

012.
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" 

Ciò consentirà di evadere tutto ciò che si desidera quindi inserire nel db. Puoi anche farlo sulla maggior parte dei modelli nella tua applicazione di rotaie usando il metodo sanitize. Ad esempio, diciamo che hai un modello chiamato Persona. Potresti farlo

Person.sanitize("O'Malley") 

Questo dovrebbe fare il trucco.

+0

Strano ... questa è stata la risposta promossa ... poi è stata cambiata ... arg. – quest

+10

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

31

Un rapido tuffo nella fonte ActiveRecord rivela il suo metodo "sanitize_sql_array" per la sanificazione del [string, bind_variable[, bind_variable]] tipo di istruzione SQL

Si potrebbe chiamare direttamente:

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: questa è una soluzione migliore in quanto è indipendente dal DB. Se l'app è distribuita su Heroku, la soluzione attualmente accettata (@quest) non funzionerà. –

+7

Quattro anni più tardi, 'sanitize_sql_array' ei suoi cugini non fanno ancora parte dell'API pubblica. Esiste un conveniente equivalente pubblico? –

2

Nel caso in cui qualcuno è alla ricerca di un esempio più concreto di soluzione @ di jemminger, qui è per inserimento di massa:

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 

Ecco la reference to sanitize_sql_array method in ActiveRecord::Base, genera la stringa di query corretta eseguendo l'escape delle virgolette singole nelle stringhe. Ad esempio la punch_line "Non lasciarti abbattere" diventerà "Non lasciare che ti buttino giù".

7

Se non si desidera che le virgolette singole in più avvolgendo la stringa che si verificano quando si utilizza la soluzione pubblicato da @konus, si può fare questo:

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

Questo restituisce "O\'Malley" invece di "'O\'Malley'"

+1

Questo non ti impedirà di SQL iniezione. – tvdeyen

+2

@tvdeyen: Sareste disposti a illustrare in che modo quanto sopra sarebbe vulnerabile, soprattutto rispetto alla risposta accettata? In definitiva, 'quote_string' dipenderà dal particolare adattatore ActiveRecord in uso. Per l'adattatore mysql2 e l'adattatore mysql astratto, 'quote' chiama' quote_string' per i valori delle stringhe e racchiude il risultato tra virgolette. Stai pensando a qualche tipo di iniezione multibyte o qualcos'altro? Grazie. – Nathan

+0

Grazie @Nathan., Funziona per me .. –