find () với nil khi không có bản ghi nào


95

Trong chương trình rails hiện tại của tôi khi tôi sử dụng một cái gì đó như

 user = User.find(10)

Khi không có người dùng nào có ID = 10, tôi sẽ có ngoại lệ như:

ActiveRecord::RecordNotFound: Couldn't find User with ID=10

Tôi có thể lấy nil thay vì tăng ngoại lệ để khi tôi làm điều gì đó như:

unless user = Challenge.find(10)
  puts "some error msg"         
end

Tôi chỉ muốn nhận nil khi không có hồ sơ và tôi không muốn sử dụng begin / Rescue

Cảm ơn


Câu trả lời:


170

Có, chỉ cần làm:

Challenge.find_by_id(10)

Đối với Rails 4 và 5:

Challenge.find_by(id: 10)

11
kỳ quặc! Tôi sẽ không bao giờ đoán rằng .find_by_*sẽ trả về con số không và .findsẽ không.
ddavison

Điều này đã thay đổi trong rails 4, hãy xem câu trả lời này stackoverflow.com/a/26885027/1438478 để biết cách mới để tìm một mục theo một thuộc tính cụ thể.
Fralcon

Tôi đã tìm thấy một vấn đề kỳ lạ với Rails 4.2 trong đó khi bạn chuyển một hàm băm là 'x' vào Something.find_by(id: x)nó sẽ tạo ra một câu lệnh SQL với tất cả các cặp thuộc tính / giá trị của hàm băm như một phần của mệnh đề WHERE. Tôi trông giống như một lỗi Rails.
Tilo

Rails (3, 4 hoặc 5) tạo ra các công find_by_...cụ tìm động cho mọi thuộc tính mà một mô hình có bao gồm :id. Vì vậy, Challenge.find_by_id(10)nên hoạt động bất kể phiên bản Rails.
Arta

Như được chỉ định bởi @MohamedIbrahim bên dưới, bạn cũng có thể thực hiện:Challenge.find(10) rescue nil
Hallgeir Wilhelmsen

31

Trong Rails 4, các công cụ tìm động - chẳng hạn như find_by_idcông cụ được sử dụng trong câu trả lời được chấp nhận - không được dùng nữa.

Về sau, bạn nên sử dụng cú pháp mới:

Challenge.find_by id: 10

4
Trong trường hợp bất cứ ai khác đang bối rối bởi điều này như tôi: Challenge.find_by(id: 10)là cách khác của văn bản này
Devin Howard

14

bạn có thể làm điều này hơi khó, chỉ cần sử dụng Giao diện truy vấn ActiveRecord.

điều này sẽ trả về nil, thay vì tăng một Exception

  User.where(:id => 10).first

Một lý do để sử dụng điều này hơn find_by_idlà vì nó có thể di động từ Rails 3 đến 4. Trong rails 4, nó find_by(:id => 10).
Gene

5

Tại sao bạn không chỉ đơn giản là bắt được ngoại lệ? Trường hợp của bạn trông giống hệt như những trường hợp ngoại lệ đã được thực hiện cho:

begin
  user = User.find(10)
rescue ActiveRecord::RecordNotFound
  puts "some error msg"
end

Nếu bạn muốn khôi phục lỗi trong khối cứu hộ (ví dụ: bằng cách đặt người dùng giữ chỗ (mẫu null)), bạn có thể tiếp tục với mã của mình bên dưới khối này. Nếu không, bạn có thể chỉ cần đặt tất cả mã của mình cho "trường hợp hạnh phúc" trong khối giữa "bắt đầu" và "giải cứu".


Btw: bạn thậm chí không cần begin…endkhối, nếu bạn đã có một khối chẳng hạn như phương thức bộ điều khiển. Trong trường hợp đó, dòng phụ duy nhất bạn cần là rescuedòng. Thanh lịch và dễ xử lý hơn nhiều so với việc kiểm tra nilbằng một ifcâu lệnh.
morgler

4

Bạn có thể thử cái này Challenge.exists?(10)


7
nó sẽ là yêu cầu sql bổ sung
fl00r Ngày

Mặc dù vậy, tôi nghĩ điều này tốt hơn đang tìm kiếm thử nghiệm
SomeSchmo

sử dụng nó nếu bạn không quan tâm đến giá trị trả về nhưng chỉ về sự hiện diện của một bản ghi trong DB
Filip Bartuzi

4

Đối với những người đang gặp khó khăn với mongoid , hóa ra là cả hai findfind_byphương pháp sẽ tạo ra ngoại lệ - bất kể phiên bản đường ray của bạn!

Có một tùy chọn (cụ thể là raise_not_found_error ) có thể được đặt thành false, nhưng khi falsey thực hiện findphương thức cũng không tăng ngoại lệ.

Vì vậy, giải pháp cho người dùng mongoid là đoạn mã kinh tởm:

User.where(id: 'your_id').first # argghhh

Bạn nghĩ gì về giải pháp giải cứu con số không của mohamed-ibrahim? Có vẻ tao nhã hơn .where(email: params[:email]).firstđối với tôi.
Wylliam Judd

1
Tôi không thích để sử dụng rescuecú pháp vì nó có thể che giấu những vấn đề như lỗi chính tả
Cristiano Mendonça

Tôi kết thúc bằng cách sử dụng giải pháp của @ morgler.
Wylliam Judd

2

chỉ đơn giản như:

user = User.find(10) rescue nil

1
Tôi muốn nói rõ hơn về lỗi nào dự kiến ​​sẽ được giải cứu, ActiveRecord :: RecordNotFound trong trường hợp này. Như đã chỉ ra câu trả lời này bởi @morgler
luizrogeriocn

2
Cá nhân tôi thấy đây là câu trả lời tốt nhất. Tôi đã nói với mã của tôi phải làm gì nếu người dùng không tìm thấy trongif user...else
Wylliam Judd

0

Bạn có thể sử dụng find_by với thuộc tính bắt buộc (trong trường hợp của bạn là id), điều này sẽ trả về nil thay vì đưa ra lỗi nếu không tìm thấy id đã cho.

user = Challenge.find_by_id(id_value)

hoặc bạn có thể sử dụng định dạng mới:

user = Challenge.find_by id: id_value

Bạn cũng có thể sử dụng where nhưng bạn phải biết rằng nơi trả về một quan hệ bản ghi đang hoạt động với 0 hoặc nhiều bản ghi mà bạn cần sử dụng trước tiên để trả về chỉ một bản ghi hoặc nil trong trường hợp 0 ​​bản ghi trả về.

user = Challenge.where(id: id_value).first
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.