Arel 및 Rails에서 LIKE 쿼리를 수행하는 방법은 무엇입니까?


115

다음과 같이하고 싶습니다.

SELECT * FROM USER WHERE NAME LIKE '%Smith%';

Arel에서의 나의 시도 :

# params[:query] = 'Smith'
User.where("name like '%?%'", params[:query]).to_sql

그러나 이것은 다음과 같습니다.

SELECT * FROM USER WHERE NAME LIKE '%'Smith'%';

Arel은 쿼리 문자열 'Smith'를 올바르게 래핑하지만 이것은 LIKE 문이므로 작동하지 않습니다.

Arel에서 LIKE 쿼리를 어떻게 수행합니까?

추신 보너스-실제로 쿼리와 일치하는 항목이 있는지 확인하기 위해 이름과 설명의 두 필드를 스캔하려고합니다. 어떻게 작동할까요?


1
보너스에 대한 아렐 답변을 업데이트했습니다.
Pedro Rolo 2014 년

답변:


275

다음은 arel에서 비슷한 쿼리를 수행하는 방법입니다.

users = User.arel_table
User.where(users[:name].matches("%#{user_name}%"))

추신:

users = User.arel_table
query_string = "%#{params[query]}%"
param_matches_string =  ->(param){ 
  users[param].matches(query_string) 
} 
User.where(param_matches_string.(:name)\
                       .or(param_matches_string.(:description)))

10
를 사용하는 것과 달리이 where("name like ?", ...)접근 방식은 다른 데이터베이스간에 더 이식성이 있습니다. 예를 들어 ILIKEPostgres db에 대한 쿼리에 사용됩니다.
dkobozev 2011

20
SQL 주입으로부터 보호됩니까?
sren

7
이것은 SQL 주입으로부터 완전히 보호하지 않습니다. user_name을 "%"로 설정해보십시오. 쿼리는 일치를 반환합니다
travis-146

5
나는 params를 사용하여 직접 SQL 주입을 User.where(users[:name].matches("%#{params[:user_name]}%"))시도했지만 TRUNCATE users;다른 쿼리를 시도했지만 SQL 측에서는 아무 일도 일어나지 않았습니다. 나에게 안전 해 보인다.
earlonrails 2013-08-28

5
.gsub(/[%_]/, '\\\\\0')MySql 와일드 카드 문자를 이스케이프하는 데 사용 합니다.
aercolino 2013-08-30

116

시험

User.where("name like ?", "%#{params[:query]}%").to_sql

추신.

q = "%#{params[:query]}%"
User.where("name like ? or description like ?", q, q).to_sql

오랜 시간이 지났지 만 @ cgg5207이 수정을 추가했습니다 (긴 이름 또는 여러 개의 긴 이름 매개 변수를 검색하거나 입력하기에 너무 게으른 경우 가장 유용합니다)

q = "%#{params[:query]}%"
User.where("name like :q or description like :q", :q => q).to_sql

또는

User.where("name like :q or description like :q", :q => "%#{params[:query]}%").to_sql

9
Rails %는 대체 문자열에서 이스케이프하지 않는 것을 어떻게 알 수 있습니까? 일방적 인 와일드 카드 만 원했다면 사용자가 %양쪽 끝에 포함 된 쿼리 값을 제출하는 것을 막을 %수있는 것은없는 것 같습니다 ( 실제로 Rails 가 쿼리 문자열에 표시 되는 것을 방지한다는 것을 알고 있지만 ActiveRecord 수준에서이를 방지해야합니다).
Steven

8
SQL 인젝션 공격에 취약하지 않습니까?
Behrang Saeedzadeh 2011

7
@Behrang no 8) User.where ( "name like % # {params [: query]} % 또는 description like % # {params [: query]} %"). to_sql은 취약하지만, 내가 보여주는 형식 , Rails는 params [: query] 이스케이프
Reuben Mallaby

주제를 벗어난 것에 대해 죄송합니다. 메서드 to_sql또는 arel 관리자 의 SQL 자식이 있습니다 . db에서 SQL을 실행하는 방법은 무엇입니까?
Малъ Скрылевъ apr

Model.where (to_sql_result)
Pedro Rolo

4

Reuben Mallaby의 대답은 매개 변수 바인딩을 사용하기 위해 더 짧게 줄일 수 있습니다.

User.where("name like :kw or description like :kw", :kw=>"%#{params[:query]}%").to_sql
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.