Hook methods trong Ruby (phần 2)
Trong bài viết trước, chúng ta đã đề cập tới 2 cách thức sử dụng hook method trong ruby là: included extended Các bạn có thể xem lại ở link sau: https://viblo.asia/dieunb/posts/mrDkMOglGzL Tiếp theo, chúng ta sẽ cùng nhau xem xét 3 cách thức khác để sử dụng hook trong ruby là: ...
Trong bài viết trước, chúng ta đã đề cập tới 2 cách thức sử dụng hook method trong ruby là:
- included
- extended
Các bạn có thể xem lại ở link sau: https://viblo.asia/dieunb/posts/mrDkMOglGzL
Tiếp theo, chúng ta sẽ cùng nhau xem xét 3 cách thức khác để sử dụng hook trong ruby là:
- prepended
- inherited
- method_missing
Prepended
Phần trước chúng ta nhận thấy, có thể sự dụng include và extend để sử dụng những hàm được định nghĩa trong module. Tuy nhiên, bên cạnh đó còn có một cách khác, đó là sử dụng prepend. Prepend được giới thiệu trong Ruby 2.0 và bản thân nó khác hoàn toàn so với include và extend. Những hàm được định nghĩa trong module nhưng khi sử dụng thông qua include hoặc extend đều có thể bị overide lại tại module/class. Nhưng với prepend thì hoàn toàn ngược lại. Chúng ta sử dụng để overide lại những hàm được định nghĩa trong module/class mà prepend module đó. Ví dụ:
Khi chưa prepend
module Person def name "My name belongs to Person" end end class User def name "My name belongs to User" end end puts User.new.name => My name belongs to User
Sau khi prepend
module Person def name "My name belongs to Person" end end class User prepend Person def name "My name belongs to User" end end puts User.new.name => My name belongs to Person
Prepend có một hàm callback tên là prepended. Hàm này sẽ được thực thi khi mà module được preprend vào một module/class khác. Ví dụ:
module Person def self.prepended(base) puts "#{self} prepended to #{base}" end def name "My name belongs to Person" end end
Ngay sau khi thực hiện chúng ta có ngay kết quả:
Person prepended to User My name belongs to Person
prepend được giới thiệu cũng là nhằm tránh việc sử dụng alias_method_chain trong Rails, vì thực sự sử dụng alias_method_chain không được đẹp.
Inherited
Inherit là một khái niệm quan trọng trong OOP. Ruby là một OOP vậy nên việc cung cấp inherit cũng không phải là một ngoại lệ. Cùng xem ví dụ:
class Person def name "My name is Person" end end class User < Person end puts User.new.name # => My name is Person
Chúng ta cũng có một hook method để nhận biết là class nào kế thừa class nào.
class Person def self.inherited(child_class) puts "#{child_class} inherits #{self}" end def name "My name is Person" end end class User < Person end puts User.new.name
Kết quả chúng ta nhận được
User inherits Person My name is Person
Inherit trong Rails Có một class quan trọng trong các Rails app có tên là Application, class này được định nghĩa trong config/application.rb. Class này thực hiện rất nhiều tác vụ như thực hiện tất cả Railties, engines, và plugin.
method_missing
Dường như method_missing là hook method được sử dụng rộng rãi nhất vì khi tìm kiếm trong những Ruby frameworks/gems/libraries, chúng ta thấy tần xuất xuất hiện của nó rất nhiều. Hàm này sẽ được gọi khi mà chúng ta đang cố gắng thực hiện một hàm mà hàm đó không có sẵn. Cùng xem ví dụ:
class Person def name "My name is Person" end end p = Person.new puts p.name # => My name is Person puts p.address # => undefined method `address' for #<Person:0x007fb730a2b450> (NoMethodError)
Chúng ta có thể sự dụng method_missing để tránh được exception và ghi lại điều đó một cách vui vẻ.
class Person def method_missing(sym, *args) "#{sym} not defined on #{self}" end def name "My name is Person" end end p = Person.new puts p.name # => My name is Person puts p.address # => address not defined on #<Person:0x007fb2bb022fe0>
Như vậy, bên trên chúng ta đã đề cập xong những hàm hook quan trọng trong Ruby. Việc sử dụng linh hoạt những hook method này sẽ làm cho ứng dụng của bạn sạch sẽ và chuyên nghiệp hơn.
Nguồn + tham khảo:
- sitepoint.com
- rubylearning.com
- railstip.com