私はプリペアドステートメントについて知っていますが、生のSQLを使用している場合、ActiveRecordは手動で値をエスケープする方法がありますか?このようなRailsの値をエスケープする(mysql_real_escape_string()と似ています)
何かがいいだろう:あなたはまだ疑問符をエスケープ値として立つフォームを使用することができます
self.escape("O'Malley") # O\'Malley
私はプリペアドステートメントについて知っていますが、生のSQLを使用している場合、ActiveRecordは手動で値をエスケープする方法がありますか?このようなRailsの値をエスケープする(mysql_real_escape_string()と似ています)
何かがいいだろう:あなたはまだ疑問符をエスケープ値として立つフォームを使用することができます
self.escape("O'Malley") # O\'Malley
を:
Dude.sanitize("O'Malley")
または
Dude.connection.quote("O'Malley")
両方とも同じ結果と:誰かに@ jemmingerのソリューションのより具体的な例を探している場合は=> "'O''Malley'"
でもModel.find_by_sql
で。
は、単に最初の要素が照会され、後続の要素がで置換される値である配列を渡しRailsのAPIドキュメントから
例:
Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
を返し
Dude.connection.quote_string("O'Malley")
を挿入するとどうなりますか? –
私はそれを掘り下げることができますが、実際にはなぜActiveRelation/ActiveModelの外に挿入していますか? –
私は 'INSERT IGNORE'をやっていて、パフォーマンスのために一つのステートメントで複数のレコードを更新しています。 –
を簡単に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"
これにより、必要なものをエスケープしてデータベースに挿入できます。また、あなたのレールアプリケーションのほとんどのモデルで、sanitizeメソッドを使ってこれを行うことができます。たとえば、Personというモデルがあるとします。あなたはすることができます。
Person.sanitize("O'Malley")
これはすべきことです。
迅速なダイビングActiveRecordのソースは、SQL文の[string, bind_variable[, bind_variable]]
タイプ
を消毒するために、その方法 "sanitize_sql_array" を明らかにあなたはそれを直接呼び出すことができます。
あなたが行うことができますsql = ActiveRecord::Base.send(:sanitize_sql_array, ["insert into foo (bar, baz) values (?, ?), (?, ?)", 'a', 'b', 'c', 'd'])
res = ActiveRecord::Base.connection.execute(sql)
Jason:これはDBに依存しないより優れたソリューションです。アプリがHerokuにデプロイされている場合、現在受け入れられている解決策(@quest)は機能しません。 –
4年後、 'sanitize_sql_array'とその従兄弟はまだパブリックAPIの一部ではありません。便利な公共の同等物はありますか? –
、ここでは一括挿入のためである:ここでは
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
は、それが生成するreference to sanitize_sql_array method in ActiveRecord::Base、あります文字列中の一重引用符をエスケープして適切なクエリ文字列を返します。例えば、punch_lineは "あなたに恋をさせてはいけません"となって、 "あなたを怒らせない"ようになります。
あなたは@konusによって投稿ソリューションを使用する場合、あなたはこれを行うことができます発生し、あなたの文字列をラップし、余分な単一引用符たくない場合:これは"O\'Malley"
代わりの"'O\'Malley'"
これはSQLからあなたを妨げません注入。 – tvdeyen
@tvdeyen:あなたは、特に受け入れられた答えと比較して、上記のものがどのような形で脆弱であるかを説明しようと思いますか?最終的に、 'quote_string'は使用されている特定のActiveRecordアダプタに依存することになります。 mysql2アダプタと抽象mysqlアダプタの場合、 'quote'は文字列値の' quote_string'を呼び出し、結果を引用符で囲みます。ある種のマルチバイト注入などを考えていますか?ありがとうございました。 – Nathan
ありがとう@Nathan。、それは私のために働く.. –
私はあなたのモデルネームが大好きです。 「おい、あなたは素晴らしいよ。 –
@NateSymer:そうです、それはあなたの意見のようです。 – Fuser97381
誰かが疑問を持っている場合は、はい、それらはまったく同じです:[sanitize calls connection.quote](http://apidock.com/rails/ActiveRecord/Base/sanitize/class) – mltsy