2012-03-14 30 views
35

Tôi có một mô hình có tên Chủ đề, có tên là trường.Đường ray: Cách tìm_một trường có chứa một chuỗi nhất định

Vì vậy, hãy nói rằng tôi có cụm từ tôi đang tìm kiếm, táo.

Nếu tôi làm một

Topic.find_by_name("apple") 

tôi nhận được một kỷ lục trở lại với tên táo. Điều đó tốt - nhưng làm cách nào để thay đổi find_by_name để có thể tìm thấy "nước táo" cũng như "quả táo" - về cơ bản, tìm tên có chứa truy vấn ban đầu hoặc khớp chính xác với truy vấn gốc?

Chỉnh sửa: Cảm ơn mọi phản hồi. Tôi đoán tôi nên đã được một chút rõ ràng hơn trước đó, nhưng nếu tôi muốn tìm bằng một tên biến (rõ ràng là tôi sẽ không muốn tìm bằng tên "táo" mọi lúc :))?

Làm cách nào để thao tác Topic.where để phù hợp với điều này? Vì vậy, một cái gì đó giống như ...

@topic = Topic.where(......., @name) 
+0

Added một chỉnh sửa câu trả lời của tôi liên quan đến chỉnh sửa mới nhất của bạn, cho tôi biết nếu điều đó giúp! – Deleteman

+0

Xem nhận xét của tôi về câu trả lời của @ Alisher để trả lời câu hỏi đã chỉnh sửa của bạn. 'Topic.where (" tên như? "," # {@ Name}% ")' sẽ là một cách. –

Trả lời

82

Tôi nghĩ rằng một cái gì đó như thế này nên làm việc:

Topic.where("name like ?", "%apple%") 

Để chứa cho chỉnh sửa của bạn:

Topic.where("name like ?", "%#{@search}%") 

Basic chuỗi suy, bạn đang sử dụng giá trị của @search bên trong chuỗi %%, vì vậy, bạn @search = "apple" thì bạn kết thúc với %apple%

+1

Bạn có nghĩ phương pháp này dẫn đến tiêm SQL không? –

+2

Theo như tôi có thể nói [ở đây] (http://rails-sqli.org/) phương thức 'where' không làm gì để bảo vệ chống lại SQL injection. Tuy nhiên, câu hỏi con chỉ thực sự được trả lời bằng cách xem xét liệu biến đó có bao giờ được tiếp xúc với đầu vào của người dùng hay không, thông qua một giá trị không được lưu trữ được lưu trữ hoặc trực tiếp. Đó sẽ là câu hỏi quan tâm. Cách tốt nhất để truy cập SQL injection là khử trùng các giá trị khi nhập ứng dụng, ngay cả trước khi lưu trữ. – GKnight

+0

làm thế nào về không chứa một chuỗi nhất định? – zx1986

0

Hãy thử

Topic.where("name like ?",'%apple%') 
Topic.find(:all, :conditions => ["name like ?","%apple%"]) 
+0

SQL injection trong ví dụ đầu tiên, nên là 'Topic.where (" tên như? ","% Apple% ")'. Thứ hai là OK. –

+0

ya bạn là chính xác. – asitmoharna

+0

Bạn cũng có thể làm điều này trong Rails 4+: 'Topic.find_by (" tên như? ","% Apple% ")' –

9

Hình như trong Rails 3 bạn sẽ muốn sử dụng nơi:

Topic.where("name ILIKE ?", "%apple%") 
+1

Không chắc chắn nếu điều này sẽ làm việc - là "~ =" hợp lệ sql? Hay bạn đang nghĩ đến mẫu phù hợp ruby ​​"= ~". Nếu vậy nó sẽ không hoạt động ở đây vì nó không phải là sql –

+0

Vâng tôi nhận thấy rằng trong bài tôi tham chiếu và chỉ lấy nó ở mệnh giá ... Tôi sẽ thay đổi thành LIKE và được an toàn. Cảm ơn! – ScottJShea

+5

Toán tử '~ =' hoạt động cho PostgreSQL - đó là một đối sánh regex. Nhưng vâng, câu trả lời của Scott sẽ hoạt động. Bạn có thể muốn sử dụng ILIKE, cho phép tìm kiếm phân biệt chữ hoa chữ thường. –

7

Đừng đặt chuỗi trực tiếp như thế. Nó được gọi là SQL injection. thay vào đó bạn nên sử dụng .where:

Topic.where("name like '?%' ", params[:name]) 
+0

Đó có phải là "tên như '?%'" Hoặc "tên như '%?%'" – varatis

+3

Điều này sẽ không hoạt động chính xác như được lưu ý vì Rails sẽ tự động trích dẫn chuỗi . Bạn sẽ cần phải tack vào '%' trước khi thay thế, ví dụ 'Topic.where (" tên như? "," # {Params [: name]}% ").' –

+0

Câu trả lời hay. –

2

Với PostgreSQL bạn cũng có thể sử dụng match operators:

Topic.where("name ~* ?", @search) 
Các vấn đề liên quan