2013-04-03 32 views
39

Có một số phép thuật Ruby/Rails ẩn nào đó chỉ đơn giản gọi một phương thức nếu nó tồn tại?Chỉ gọi phương thức nếu nó tồn tại

phép nói rằng tôi muốn gọi

resource.phone_number 

nhưng tôi không biết trước nếu nguồn lực đáp ứng phone_number. Một cách để thực hiện việc này là

resource.phone_number if resource.respond_to? :phone_number 

Đó không phải là tất cả những gì đẹp nếu được sử dụng sai địa điểm. Tôi tò mò nếu một cái gì đó tồn tại mà làm việc nhiều hơn dọc theo dòng cách try được sử dụng (resource.try(:phone_number)).

+0

Như một ví dụ cực đoan, tôi khuyên bạn nên ghi đè 'method_missing' của' Object' để trả về 'nil' trong trường hợp này. Đây là kinh dị để gỡ lỗi. Và một số người sẽ xem xét phong cách xấu, meta và không cần thiết. – User

+0

@Người dùng bah, không phải là một nỗi buồn. Bạn chỉ đơn giản là để rewing một ngăn xếp trở lại nơi nil ngoại lệ đã được ném :-) – mudasobwa

+4

bằng cách sử dụng 'respond_to' là lựa chọn tốt nhất – apneadiving

Trả lời

28

Nếu bạn không hài lòng với cú pháp ruby ​​tiêu chuẩn cho điều đó, bạn có thể tự do:

class Object 
    def try_outside_rails(meth, *args, &cb) 
    self.send(meth.to_sym, *args, &cb) if self.respond_to?(meth.to_sym) 
    end 
end 

Bây giờ là:

resource.try_outside_rails(:phone_number) 

sẽ cư xử như bạn muốn.

+3

bạn đang ghi đè phương thức 'try' hiện có trong Rails – apneadiving

+0

Ruby có thể khá tuyệt vời. Điều này là không đủ định kỳ cho tôi để xác định một phương pháp của riêng tôi cho nó, tôi chỉ tự hỏi nếu nó đã tồn tại một phương pháp cho nó. – Frans

+1

@apneadiving Ai đã nói về 'Rails'? – mudasobwa

10

Tôi biết đây là bài đăng rất cũ. Nhưng chỉ muốn biết nếu điều này có thể là một câu trả lời có thể và liệu tác động là như nhau hay không.

resource.try(:phone_number) rescue nil 

Cảm ơn

+3

Với Rails 4 bạn thậm chí không cần 'giải cứu': http://api.rubyonrails.org/classes/Object.html#method-i-try –

+8

Phương pháp 'thử' không phải là về việc kiểm tra xem một phương pháp tồn tại, đó là về việc bảo vệ bạn khỏi một con số không. Ví dụ. 'nil.try (: some_method)' sẽ trả về 'nil' thay vì đưa ra một ngoại lệ, nhưng' valid_reference.try (: non_existant_method) 'sẽ vẫn thất bại (trừ khi bạn đã làm xong, bạn thêm' rescue nil'). – neuronaut

+1

Nó không phải là một thực hành tốt để sử dụng cứu hộ trong dòng chảy bình thường của một chương trình. Ném và bắt ngoại lệ bổ sung thêm chi phí cho chương trình. – Josh

4

Bắt đầu từ Ruby 2.3.0 (mà vẫn còn ở thời điểm này trong bản xem trước), bạn có thể sử dụng mới safe navigation operator:

resource&.phone_number 

Ngoài ra nếu bất cứ ai quan tâm đến cú pháp được chọn, tôi khuyến khích bạn kiểm tra các cuộc thảo luận feature request trong hệ thống theo dõi vấn đề của Ruby. Tôi cũng đã giải thích lý do trong câu trả lời của tôi here.

+0

Toán tử '& .' có kiểm tra xem phương thức được định nghĩa hay không, hoặc nó chỉ kiểm tra xem đối tượng có phải là nil không? –

+0

Không, AFAIK nó chỉ kiểm tra nếu câu lệnh đầu tiên là _nil_ và nếu nó đánh giá tất cả là _nil_. Nếu phương pháp tiếp theo không được xác định, nó sẽ ném như nó sẽ với cuộc gọi bình thường. Tôi sẽ tìm nguồn. –

+0

Đánh giá dựa trên khả năng rất hạn chế của tôi để đọc nguồn MRI, có vẻ như tôi đã giả định chính xác. Có thể thấy sự khác biệt này tại đây (https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/52214/diff) (yêu cầu đăng nhập). Việc triển khai dường như chỉ bỏ qua cuộc gọi tiếp theo nếu có _nil_ được đánh giá. –

0

Nếu A.c được xác định và A.aA.b không, bạn có thể làm A.a rescue A.b rescue A.c và nó sẽ hoạt động như một nét duyên dáng. Bạn sẽ phá vỡ một số quy tắc ngớ ngẩn, mặc dù.

Các vấn đề liên quan