Tạo Và Sử Dụng Module Trong Ruby on Rails
Chào các bạn, như bài viết trước mình cũng có 1 bài viết giới thiệu về Ruby on Rails, bài biết hôm nay mình lại tiếp tục với chủ đề với tạo và sử dụng Module như thế nào trong Ruby on Rails. Trong Ruby on Rails với tính linh hoạt của module nên nó được sử dụng khá nhiều trong các dự ...
-
Chào các bạn, như bài viết trước mình cũng có 1 bài viết giới thiệu về Ruby on Rails, bài biết hôm nay mình lại tiếp tục với chủ đề với tạo và sử dụng Module như thế nào trong Ruby on Rails.
-
Trong Ruby on Rails với tính linh hoạt của module nên nó được sử dụng khá nhiều trong các dự án.
-
Vậy Module là gì, tạo như thế nào và sử dụng ra sao, sau bài viết này các bạn có thể dễ dàng hình dung ra được.
-
Trong Ruby, có 2 cách sử dụng method của module. Cách thứ nhất là 'nhúng' (mixin) và dùng như instance method và cách thứ hai là dùng theo kiểu module function.
Cách thứ nhất: Mixin và dùng như instance methods
module BMW def color puts "Black" end end class Car include BMW end Car.new.color # => Black
Cách thứ hai: module functions
module BMW def self.color puts "Black" end end BMW.color # => Black
Ngoài ra bạn có thể kết hợp 2 cách trên, như ví dụ bên dưới.
module BMW def color puts "Black" end module_function :color end class Car include BMW end BMW.new.color # => Black Car.color # => Black
- Như các ví dụ tôi đưa ra ở trên các bạn đã dần hiểu đc cách tạo và sử dụng Module trong Ruby on Rails như thế nào rồi đúng khong nào. (go) Bây giờ chúng ta sẽ tìm hiể kỹ hơn ở phần dưới nhé.
- Một trong những công cụ mạnh nhất của Ruby on Rails là Module, nó được sử dụng như một namespace của class trong Ruby. Ví dụ chúng ta tạo một Module đơn giản sau:
module Sample class Hello puts "Hello World." end end
- Ở ví dụ trên, chúng ta tạo ra class Hello được nằm trong Module Sample, điều đó có nghĩa là khi chúng ta tạo ra một instance của Hello thay vì:
h = Hello.new
- Hoặc bạn có thể gọi bằng cách thếm tiền tố namespace và dấu hai chấm:
h = Sample::Hello.new
1. Module và included callback
- Ruby cung cấp một hàm callback có tên included cho module. Hàm callback này sẽ được gọi mỗi khi module được included vào một module hoặc class khác. Cách dùng included rất đơn giản, bạn có thể xem ví dụ mình viết như sau:
# car.rb module BMW def BMW.included(mod) puts "#{self} included in #{mod}" end end module Car include BMW end
- Khi chạy file car.rb trên sẽ được kết quả như sau:
$ ruby car.rb BMW included in Car
- included có thể được dùng để tách các phần logic giống nhau vào một module dùng chung. Chẳng hạn trong ví dụ sau ta có 2 class Entry và Comment, cả 2 class đều định nghĩa các hàm như posted_at và cùng gọi các helper như validates_presence_of
class Entry validates_presence_of :user_id def posted_at created_at.strftime("%Y/%m/%d") # formated post time end end class Comment validates_presence_of :user_id def posted_at created_at.strftime("%Y/%m/%d") # formated post time end end
- Dùng included ta dễ dàng move các logic này vào một module riêng, cụ thể như sau:
module Post def self.included(base) base.class_eval do validates_presence_of :user_id end end def posted_at created_at.strftime("%Y/%m/%d") end end class Entry include Post end class Comment include Post end
2. Class methods
- Khi một module được include vào một class, mặc định class đó sẽ access được các instance method được định nghĩa trong module đó nhưng lại không gọi được các class method. Chẳng hạn như hàm find_by_user_id trong ví dụ sau:
module Post def posted_at created_at.strftime("%Y/%m/%d") end def self.find_by_user_id # ... end end class Entry include Post end class Comment include Post end
- Chúng ta sẽ xét các trường hợp gọi hàm find_by_user_id
# Result Ok Entry.new.posted_at -> Ok Comment.new.posted_at -> Ok # Result Eror Entry.find_by_user_id(1) -> NoMethodError Comment.find_by_user_id(2) -> NoMethodError
Môt instance method được định nghĩa trong module nhưng lại không gọi được các class method
- Để giải quyết vấn đề này chúng ta sử dụng callback included
module Post def self.included(base) base.extend(ClassMethods) end module ClassMethods def find_by_user_id ... end end end
-
Ở trên ta dùng function base của class/module để extend các class method. Sử dụng cách này, các class/module include Post sẽ access được hàm find_by_user_id đã được định nghĩa.
-
Như vậy kết quả của chúng ta sẽ là như sau:
# Result Ok Entry.new.posted_at -> Ok Comment.new.posted_at -> Ok # Result Ok Entry.find_by_user_id(1) -> Ok Comment.find_by_user_id(2) -> Ok
- Trong các dự án của chúng ta, việc viết code đúng và đẹp làm một vấn đề hết sức quan trọng. Chính vì vậy hiểu dõ cách hoạt động của module sẽ giúp ích cho ta rất nhiều về vấn đề đó.
- Ở bài viết này mình đã giới thiệu hai cách sử dụng của module trong Ruby on Rails, rất mong nhận được sự đóng góp và ý kiến của các bạn để bài viết có thể đầy đủ hơn. Thanks All!