6

나는 username, last_name 및 first_name에서 문자열을 확인해야하는 간단한 검색 기능을 구현하고 있습니다. 나는 오래된 RailsCast에이 액티브 방법을 본 적이 : 그것은 이름, LAST_NAME과 이름의 키워드를 검색하고 경우 레코드를 반환하도록레일스 ActiveRecord - 다중 속성 검색

http://railscasts.com/episodes/37-simple-search-form

find(:all, :conditions => ['name LIKE ?', "%#{search}%"]) 

하지만 내가 그것을 어떻게해야합니까 필드 중 하나가 용어와 일치합니까?

RailsCast의 코드가 SQL 삽입에 취약한 지 궁금합니다.

고마워요! 나는 당신의 모델 이름을 가정

답변

20

모델 - 당신은 실제 쿼리를 수행 할 때 당신의 실제 모델 이름으로 대체 : SQL 주입에 대한 걱정에 대해

Model.where("name LIKE ? OR last_name LIKE ? OR first_name LIKE ?", "%#{search}%","%#{search}%","%#{search}%") 

을 - 코드 조각 모두 SQL 주입에 면역 . 문자열을 WHERE 절에 직접 포함시키지 않는 한 괜찮습니다. 사출 발생하기 쉬운 코드 예제는 다음과 같습니다

Model.where("name LIKE '#{params[:name]}'") 
+0

내가 필요한 것. 그것을 분명히 설명해 주셔서 감사합니다! – maru

+0

컨트롤러가 단지'params [: search]'가 아닌'params '전체를 전달하도록 변경되고 쿼리에서'% # {params [: search]} %'대신'% # {search} % "'. 여전히 SQL 인젝션의 영향을받지 않습니까? – Dennis

+0

@Dennis 그렇습니다. 당신이 사용하는 한? 당신은 괜찮습니다 쿼리에서 그들을 대체하기 위해 추가 인수를 전달합니다. –

8

선택한 답변이 작동하지만, 나는 당신이 두 경우 모두 실패하기 때문에 검색 "라울 리에라"를 입력하려고하면 그것이 파괴 것으로 나타났습니다 라울 때문에 리에라 중 하나를 내 이름 또는 마지막 이름이 아닙니다 .. 내 이름과 성입니다 ... 내가이 일을

Model.where("lower(first_name || ' ' || last_name) LIKE ?", "%#{search.downcase}%") 
+0

이렇게 대답하는 것이 더 유용하다는 것을 알았습니다. 감사! –

+0

downcase보다는 ILIKE를 사용하는 것이 더 좋지 않겠는가? DB가 처리하도록하십시오. –

+0

last_name 또는 first_name이 nil과 같은 경우 작동하지 않습니다. 그렇다면 기본 빈 문자열 값을 이름과 성으로 설정해야합니다 –

0

가장 좋은 방법을 수행하여 그것을 해결은 다음과 같습니다

Model.where("attr_a ILIKE :query OR attr_b ILIKE :query", query: "%#{query}%") 
0

으로 Arel, 너는 쓰는 것을 피할 수있어. 다음과 같이 수동으로 SQL을 입력하십시오.

Model.where(
    %i(name first_name last_name) 
    .map { |field| Model.arel_table[field].matches("%#{query}%") 
    .inject(:or) 
) 

이 필드는 일치시킬 필드 목록이 동적 인 경우에 특히 유용합니다.

관련 문제