Decorator Ruby on Rails


Xin chào tất cả mọi người, trong bài viết này mình sẽ giới thiệu với các bạn cách để áp dụng Decorator vào Ruby on Rails.

Sau đây là những câu hỏi cần được giải quyết của bài viết này :



1. Decorator là gì ?

2. Decorator dùng để làm gì ?

3. Làm sao để định nghĩa một Decorator ?

4. Decorator hoạt động như thế nào ?

5. Sử dụng Decorator trong Rails như thế nào ?




1. Decorator là gì ?



- Decorator là một mẫu thiết kế (Design pattern) thường được dùng để thay đổi hành vi, chức năng của hàm(function) hoặc lớp (class) mà không cần phải thay đổi code của hàm hoặc lớp.

Về cơ bản Decorator giống như một lớp vỏ bọc (wrapper), nó thay đổi hành vi(behavior) của code trước và sau khi gọi hàm chính (hàm được decorate).


2. Decorator dùng để làm gì ?


Tại sao chúng ta cần Decorator?

Cho phép tái sử dụng code.

 - Mở rộng các hàm, hoặc lớp mà không cần phải thay đổi code có sẵn —> không cần test lại.
- Ví dụ :  trong chương trình của bạn bạn cần kiểm tra quyền (permission) của người dùng trước khi thực hiện hàm. Bạn có thể phải thêm code vào tất cả các hàm đã có để kiểm tra. Thay vào đó với decorator, bạn chỉ cần định nghĩa một decorator và khai báo nó trước hàm.


3.  Làm sao để định nghĩa một Decorator ?


Decorator cũng là một hàm chỉ khác là hàm decorator nhận vào một hàm và kết quả trả về của nó là hàm sau khi được decorate.
Như vậy để định nghĩa một decorator chỉ đơn giản là định nghĩa một hàm nhận vào một hàm khác và trả về một hàm mới có prototype tương đương với hàm nhận vào.


Ví dụ 1:
  def ten_decorator(f)
      def wrapper(ten)
        chuoi_moi = "Ten tui la #{ten}"        f(chuoi_moi)      end         end
xuat_ten( ten )
puts ten
CHÚ Ý QUAN TRỌNG: hàm wrapper và hàm f phải có tham số phù hợp với nhau. Ví dụ như hàm f nhận vào chỉ 2 tham số thì hàm decorator không thể nhận vào 3 tham số hoặc 1 tham số.

4. Decorator hoạt động như thế nào ?

Như trong ví dụ ở trên:
ten_decorator nhận vào hàm f, sau đó bọc hàm f trong hàm wrapper của nó và trả về hàm wrapper. Hàm wrapper có nhiệm vụ gắn thêm thông tin vào tên rồi mới gọi thực hiện hàm f với chuỗi mới.

Rõ ràng với việc sử dụng cú pháp decorator thì code sẽ ngắn gọn và đơn giản hơn. Developer không phải gọi decorator mỗi lần sử dụng mà trình thông dịch sẽ làm việc đó.
Đối với hàm sử dụng nhiều decorator

5. Sử dụng Decorator trong Rails như thế nào ?

Trong rails để  việc tạo 1 Decorator dễ dàng và nhanh chóng chúng ta sẽ dùng gem Draper

Thêm vào Gemfile :


gem 'draper', '~> 1.3'
Mở terminal và run các lệnh : 


  bundle install

Tạo decorator file :

rails generate decorator Article
File tạo được sẽ trông như thế này :
class ArticleDecorator < Draper::Decorator
  
end
Ví dụ :  table Article có 1 column là created_at và chúng ta muốn format nó lại cho đẹp . Thông thường thì chúng ta sẽ viết 1 function ở helper để chuyển  đổi định dạng.
Với decorator ta sẽ viết 1 function cho nó với tên giống với tên method là created_at :
class ArticleDecorator < Draper::Decorator
  def created_at
    helpers.content_tag :span, class: 'time' do
         object.created_at.strftime('%m/%d/%y')
    end
  end
end

Và ở controller ta sẽ thêm vào decorate như thế này để sử access decorator cho method đó  :


@article = Article.first.decorate

Và ở view : 
@article.created_at
sẽ được hiển thị ra với cấu trúc HTML trông như thế này :
07/01/2016


Ngoài ra, các bạn cũng thể tìm hiểu sâu hơn tại document của Draper .


KẾT LUẬN : 

     Việc sử dụng decorator giúp cho code ở view được trong sáng rõ ràng. Tránh việc các logic được viết ngay ở view hoặc có quá nhiều method ở helper.  Tối ưu việc sử dụng các function 1 cách hiệu quả nhất. Dễ debug và mở rộng ứng dụng.




Comments