Understanding method missing
Mở đầu Trong bài viết này chúng là sẽ đi tìm hiểu về method_mising và respond_to_mising? để cùng xem họ đã tạo ra và sử dụng nó như thế nào. Chúng ta sẽ tại tạo lại class StringInquirer trong Ruby on Rails như là một cách để chứng minh cái gì đang diễn ra và làm thế nào để có thể sử dụng nó trong ...
Mở đầu
Trong bài viết này chúng là sẽ đi tìm hiểu về method_mising và respond_to_mising? để cùng xem họ đã tạo ra và sử dụng nó như thế nào. Chúng ta sẽ tại tạo lại class StringInquirer trong Ruby on Rails như là một cách để chứng minh cái gì đang diễn ra và làm thế nào để có thể sử dụng nó trong các ứng dụng thực tế.
StringInquirer là gì
Với tất cả những ai đã làm việc với Rails application, thì có lẽ chúng ta đã từng kiểm tra tại một thời điểm, ứng dụng đang chạy trên môi trường nào. Để kiểm tra điều này chúng ta có thể gọi Rails.env.staging?. Những gì tôi biết tại sao rails làm được việc này là gì env là một instance của class StringInquirer
StringInquirer cho phép chúng ta so sánh String với một cái gì đó bằng cách hỏi staging? hoặc env == "staging"
NoMethodError
Có thể chúng ta đã nhìn thấy các ngoại lệ NoMethodError nhiều lần trong khi lập trình Ruby. Đoạn code dưới đây sẽ tạo ra ngoại lên NoMethodError vì method happy? không tồn tại.
class StringInquirer < String end mood = StringInquirer.new("happy") mood.happy?
Khi chúng ta gọi happy? Ruby sẽ kiểm tra xe đối tượng trả về là method... hay nói một cách khác, nếu method happy? tồn tại với tên đó trong đối tượng hiện tại hoặc bất kỳ class khác trong hệ thống chuỗi phân cấp.
Trong trường hợp không thể tìm thấy method happy? nó sẽ bắn ra exception. Nhưng Ruby cho phép chúng ta implement một method là method_missing.
method_missing nhận tên của method và các đối số được truyền cho method được gọi. Nếu chúng ta thêm method_missing vào class của chúng ta và in ra các giá trị. Đấy là ý tưởng về việc chúng ta đang làm.
class StringInquirer < String private def method_missing(method_name, *arguments) puts method_name.inspect puts arguments.inspect end end
mood = StringInquirer.new("happy") mood.happy? :happy? []
Bây giờ chúng ta muốn kiểm tra một method_name với ký tự ? ở cuối . Đầu tiên, hãy kiểm tra xem nếu đầu vào, method_name kết thúc bằng một dấu ?, nếu đúng, thì kiểm tra xem phần bắt đầu của method_name tương đương với día trị chuỗi chúng ta đã khai báo (ex: "happy"). Nếu method truyên vào không kết thúc bằng ? thì chúng ta khai báo super để gọi đến các method ở class String
class StringInquirer < String private def method_missing(method_name, *arguments) if method_name[-1] == '?' self == method_name[0..-2] else super end end end
Với việc cập nhật lại như này, đoạn code sẽ trả về true khi chúng ta gọi happy? và false nếu chúng ta gọi một thứ bất kỳ (ex: sad?)
Does my object respond to?
Thỉnh thoảng trước khi gọi một method nào đó chúng ta thường kiểm tra xem object có đáp ứng được method mình đang gọi hay không. Để làm được điều đó chúng ta có thể sử dụng method respond_to?
"Happy".respond_to?(:length) # => true
Vấn đề ở đây, các method happy? hay sad? không thực sự tồn tại. Có một method khác mà chúng ta có thể implement để giúp chúng ta xử lý các trường hợp không thể tìm thấy method cụ thể được gọi. Đó gọi là respond_to_missing?. respond_to_missing? nhận method name và các giá trị khác được gọi là include_private (chúng ta không cần quan tâm về nó bây giờ). Trong trường hợp này, chúng ta muốn kiểm tra các method được gọi có kết thúc bằng ? hay không.
Để làm được việc này chúng ta lại về với class StringInquirer nơi chúng ta sẽ implement 2 method method_missing and respond_to_missing?
class StringInquirer < String private def respond_to_missing?(method_name, include_private = false) method_name[-1] == '?' end def method_missing(method_name, *arguments) if method_name[-1] == '?' self == method_name[0..-2] else super end end end
Chúng ta có thể sử dụng class như sau.
mood = StringInquirer.new("happy") p mood.happy? # => true p mood.sad? # => false p mood.respond_to?(:happy?) # => true
Concluding thoughts
Mình đã đề cập và sử dụng đến 2 method là method_missing và respond_to_missing để thực hiện và hiểu một chút về "Meta programing". Cho phép code của chúng ta đặt các câu hỏi cho chính nó và tạo ra chức năng mới một cách nhanh chóng.
Lần sau, khi sử chúng ta sử dụng Rails.env.development? chúng ta sẽ biết được chuyện gì đã xảy ra để làm được điều này.
Tham khảo
Bài viết được dịch từ:
https://www.leighhalliday.com/understanding-method-missing