2013-03-13 9 views
13

Gần đây tôi đã biết rằng bạn có thể sử dụng rescue trên một dòng mã trong trường hợp xảy ra sự cố trên dòng đó (xem http://www.rubyinside.com/21-ruby-tricks-902.html Mẹo # 21). Tôi có một số mã được sử dụng để trông như thế này:Ruby Oneline Rescue

if obj['key'] && obj['key']['key2'] && obj['key']['key2']['name'] 
    name = obj['key']['key2']['name'] 
else 
    name = '' 
end 

Với phương pháp rescue, tôi tin rằng tôi có thể thay đổi mã đó vào một cái gì đó như thế này:

name = obj['key']['key2']['name'] rescue '' 

Nếu một ngoại lệ bằng không được ném vào bất kỳ mức độ truy cập vào băm, nó sẽ bị bắt bởi cứu hộ và cho tôi '', đó là những gì tôi muốn. Tôi cũng có thể chọn đặt tên thành nil nếu đó là hành vi mong muốn.

Có bất kỳ mối nguy hiểm nào đã biết khi thực hiện việc này không? Tôi hỏi vì điều này có vẻ quá tốt là đúng. Tôi có rất nhiều mã xấu xí mà tôi muốn loại bỏ nó trông giống như ví dụ mã đầu tiên.

+0

Cho rằng sử dụng cụ thể, một inline 'giải cứu 'là an toàn. Hãy * RẤT * cẩn thận khi sử dụng nó ở cuối cuộc gọi phương thức, trong đó một thứ khác có thể làm tăng ngoại lệ, có thể do lỗi I/O hoặc thiếu thông tin cơ sở dữ liệu. Gỡ lỗi những tình huống đó thực sự, thực sự, khó khăn và có thể khiến bạn phát điên. –

Trả lời

11

Đọc tốt! Nhưng nó sẽ đạt hiệu suất của bạn. Theo kinh nghiệm của tôi, rescue chậm hơn nhiều khi được kích hoạt và hơi chậm hơn khi không. Trong mọi trường hợp, if nhanh hơn. Điều khác cần xem xét, là ngoại lệ không nên được mong đợi và bạn là loại với mã này. Có một hash rất sâu lồng nhau có thể là một mùi tốt mà một refactoring là nede

+0

Các băm đến từ một dịch vụ web trả về JSON lồng nhau sâu sắc. Tôi phải kiểm tra cho tất cả các nils trên đường đi bởi vì các dịch vụ thường để lại các yếu tố lồng nhau nil. –

+0

Nếu đây là trường hợp tôi khuyên bạn nên sử dụng một viên ngọc để tăng cường băm của bạn, để làm cho mã của bạn dễ đọc hơn: https://github.com/intridea/hashie. – Leito

+0

Đặc biệt, Mash (https://github.com/intridea/hashie#mash) xem các ví dụ cho thử nghiệm đa cấp, nó có thể không nhanh hơn ifs, nhưng nó sẽ cải thiện mã của bạn! – Leito

-1

Kernel :: tăng có thể là đáng giá để nhìn vào cũng

if obj['key']['key2']['name'] 
    name = obj['key']['key2']['name'] 
else 
    raise '' 
end 
+0

Mã của bạn không giống như OP. Đi cho rằng một thử trong 'irb' và xem tại sao. –

+0

Cảm ơn Gavin, tôi thấy OP đã thay thế và không tăng lỗi. Tôi sẽ xem xét điều này nhiều hơn. – aug2uag

4

ví dụ cụ thể này bây giờ có thể đạt được với Ruby 2.3 của dig method.

name = obj.dig 'key', 'key2', 'name' 

Điều này sẽ truy cập an toàn obj['key']['key2']['name'], trả về 0 nếu bạn không thực hiện được bất kỳ bước nào.

(Nói chung, nó thường được khuyên nên sử dụng ngoại lệ duy nhất cho thực tế, không lường trước được, lỗi, mặc dù nó hoàn toàn dễ hiểu trong một ví dụ như thế này nếu cú ​​pháp làm cho nó cồng kềnh.)