Tạo Và Sử Dụng Module Trong Ruby on Rails
Bài đăng này đã không được cập nhật trong 4 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ụngModulenhư thế nào trongRuby on Rails.
- 
Trong Ruby on Railsvới tính linh hoạt củamodulenên nó được sử dụng khá nhiều trong các dự án.
- 
Vậy Modulelà 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 ModuletrongRuby on Railsnhư 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 RailslàModule, nó được sử dụng như mộtnamespacecủaclasstrongRuby. 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ộtinstancecủa Hello thay vì:
h = Hello.new
- Hoặc bạn có thể gọi bằng cách thếm tiền tố namespacevà dấu hai chấm:
h = Sample::Hello.new
1. Module và included callback
- Ruby cung cấp một hàm callbackcó tênincludedchomodule. Hàmcallbacknày sẽ được gọi mỗi khimoduleđượcincludedvào mộtmodulehoặcclasskhác. Cách dùngincludedrấ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
- includedcó thể được dùng để tách các phần logic giống nhau vào một- moduledùng chung. Chẳng hạn trong ví dụ sau ta có 2 class- Entryvà- Comment, cả 2 class đều định nghĩa các hàm như- posted_atvà cùng gọi các- helpernhư- 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 includedta dễ dàng move các logic này vào mộtmoduleriê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đượcincludevà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 trongví 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 trongmodulenhư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 basecủaclass/moduleđểextendcácclass method. Sử dụng cách này, cácclass/module include Postsẽ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 modulesẽ 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 moduletrongRuby 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
 
  
 