Giới thiệu module Rails Concern
Kể từ bản Rails 4, một thư mục mặc định được tạo ra mỗi khi tạo project mới, đó là thư mục concerns. Ta sẽ tìm hiểu về module concern trong bài viết này.
But first, let’s return to Ruby’s realm
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, ví dụ sau được trích từ document của Ruby
Khi chạy file test.rb
trên sẽ được kết quả:
$ ruby test.rb
A included in Enumerable
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
Dùng included
ta dễ dàng move các logic này vào một module riêng, cụ thể như sau:
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:
Một cách để workaround chính là sử dụng callback included
Trong ví dụ 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 Postable
sẽ access được hàm find_by_user_id
đã được định nghĩa.
Module Concern
Các ví dụ ở trên chính là cách hoạt động của module Concern
. Với việc sử dụng Concern
ta viết lại module Postable
đơn giản như sau:
Ngoài ra, module concern còn giúp giải quyết vấn đề dependency. Như trong ví dụ sau, module B phụ thuộc vào module A
Ta thấy class C chỉ muốn sử dụng module B, nhưng lại phải include thêm module A(do B phụ thuộc vào hàm method_of_module_a
của A).
Nhưng với việc sử dụng Concern vấn đề dependency đã được giải quyết. Ta viết lại đoạn code trên như sau:
Chi tiết về module Concern có thể tham khảo tại:
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb