2011-01-14 4 views

답변

53

당신은 할 수 있습니다 :

Dude.sanitize("O'Malley") 

또는

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

같은 결과 두 가지 모두의 경우 누군가에 => "'O''Malley'"

+3

나는 당신의 모델 이름을 좋아합니다. '야, 너 멋지다. –

+6

@NateSymer : 예, 글쎄, 그건 당신 생각과 같습니다. – Fuser97381

+2

다른 사람이 궁금해하는 경우에는 네, 정확히 동일합니다 : [sanitize calls connection.quote] (http://apidock.com/rails/ActiveRecord/Base/sanitize/class) – mltsy

4

에도 Model.find_by_sql와 함께.

단순히 제 소자 쿼리 인 배열을 전달하고 후속 요소로 치환 될 수있는 값이다

예 레일 API 문서에서 :.

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

을 반환 삽입하면 어떨까요? –

+1

나는 그것을 파헤 칠 수 있지만 실제로 : 왜 ActiveRelation/ActiveModel 외부에 삽입하고 있습니까? –

+1

나는 INSERT IGNORE를하고 있는데 성능을 위해 한 문장으로 여러 레코드를 업데이트하고있다. –

19

쉽게 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") 

그 트릭을 수행해야합니다.

+0

이상한 ... 이것은 승진 된 답변이었습니다 ... 그 다음 변경되었습니다 ... arg. – quest

+10

Mysql2 보석으로 :'Mysql2 :: Client.escape ("O'Malley") # => "O \\ 'Malley"' – Duke

31

는 액티브 소스에 빠른 다이빙은 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) 
+2

제이슨 : 이것은 DB 독립적이기 때문에 더 나은 해결책입니다. 앱이 Heroku에 배포 된 경우 현재 허용되는 솔루션 (@quest)이 작동하지 않습니다. –

+7

4 년 후'sanitize_sql_array'와 그 사촌들은 여전히 ​​공개 API의 일부가 아닙니다. 편리한 공공 시설이 있습니까? –

2

는 @의 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 

reference to sanitize_sql_array method in ActiveRecord::Base, 그것은 생성 문자열에서 작은 따옴표를 이스케이프 처리하여 적절한 쿼리 문자열. 예를 들어 punch_line은 "그들이 당신을 내버려 두지 않게하십시오"는 "돈을 버려서는 안된다"고 할 것입니다. 당신은 당신이 @konus에 의해 게시 솔루션을 사용할 때 발생하는 귀하의 문자열을 포장 여분의 작은 따옴표를 원하지 않는 경우

7

, 당신은이 작업을 수행 할 수 있습니다

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

"O\'Malley" 대신 "'O\'Malley'"

+1

이렇게하면 SQL에서 벗어날 수 있습니다. 주입. – tvdeyen

+2

@ tvdeyen : 특히 위의 답변에 비해 위의 사항이 어떤 방식으로 취약한지를 설명해 주시겠습니까? 궁극적으로,'quote_string'는 사용중인 특정 ActiveRecord 어댑터에 의존하게 될 것입니다. mysql2 어댑터와 추상 mysql 어댑터의 경우, quote는 문자열 값에 대해'quote_string'을 호출하고 결과를 따옴표로 묶습니다. 어떤 멀티 바이트 주입이나 다른 것을 생각하고 있습니까? 고맙습니다. – Nathan

+0

고마워요 @ 네이선., 그것은 나를 위해 작동 .. –

관련 문제