+5

Decorator in Rails

Khái niệm Decorator

Như chúng ta đã biết, hệ thống RoR được xây dựng dựa trên mô hình MVC, trong đó:

  • Model có vai trò xử lí logic và dữ liệu
  • View nhận trách nhiệm hiển thị dữ liệu
  • Controller là nơi trung gian điều phối dữ liệu, cầu nối giữa modelview Theo lí thuyết, model thường là nơi mà chúng ta tập trung những phương thức, hàm xử lí logic phức tạp. Tuy nhiên điều đó chỉ áp dụng được với những hệ thống nhỏ, còn với những dự án lớn, đòi hỏi nhiều công đoạn xử lý cầu kì, thì model không còn là nơi thích hợp nữa, nếu ta cứ cố chấp nhồi nhét quá nhiều hàm logic vào nó, thì model sẽ ngày một cồng kềnh hơn, và cũng vô cùng vất vả cho công đoạn maintain về sau. Để khắc phục vấn đề này, Rails có thêm các công cụ hỗ trợ rất mạnh mẽ, và 1 trong số đó chính là Decorator Decorator bản thân nó cũng là một pattern, có vai trò là cầu nối giữa modelview. Nó như là một lớp con trung gian, cho phép chúng ta tạo thêm các phương thức xử lý cho đối tượng mà không gây ảnh hưởng đến đối tượng khác trong cùng một lớp.

Implement

Có nhiều cách để chúng ta implement Decorator trong project của mình. Có thể thêm bằng cách thủ công, hoặc sử dụng một số gem như ActiveDecorator, Draper. Chúng ta sẽ thử implement bằng tay trước. Giả sử như chúng ta có bài toán về xây dựng ứng dụng quản lí thông tin người dùng chẳng hạn, bao gồm first_name, last_name, email.. và cần hiển thị trên browser first_namelast_name của user đó. Trường hợp này chúng ta sẽ cần dùng đến Decorator với cái tên UserDecorator. Trước tiên, xây dựng hệ thống quản lí User cơ bản bằng scaffold:

rails g scaffold User first_name:string last_name:string email:string

Sau đó tạo thêm folder decorators với đường dẫn app/decorators Chúng ta tiếp tục tạo UserDecorator trong decorators, sau đó định nghĩa một method xử lí việc lấy thông tin first_name, last_name của user:

module UserDecorator
  def full_name
    if first_name.blank? && last_name.blank?
      "Got nothing to show"
    else
      "#{first_name} #{last_name}"
    end
  end
end

Để các đối tượng của lớp User có thể dùng được method full_name của UserDecorator, chúng ta chỉ cần include nó vào trong class User là ổn:

class User < ActiveRecord::Base
   include UserDecorator
   ...
end

Rồi, giờ thì phía trên view chúng ta chỉ cần gọi method full_name ra cho bất kì instance variable nào của User thôi:

<p>
  <strong>Full name:</strong>
  <%= @user.full_name %>
</p>

Ok, đó là cách mà chúng ta có thể implement Decorator bằng tay, tiếp đến sẽ là cách để sử dụng nó thông qua gem Draper: Bước thứ nhất là thêm gem file rồi bundle:

gem "draper"

Sau đó chúng ta khởi tạo UserDecorator:

rails generate decorator UserDecorator

Chúng ta được file user_decorator.rb như sau:

class UserDecorator < Draper::Decorator
    delegate_all
end

Rồi sau đó chúng ta có thể tùy ý "decorate" các method bên trong nó thôi, tương tự như trong cách đầu tiên nhé. Sau khi "decorate" xong, chúng ta chỉ cần gọi kiểu .decorate với mọi đối tượng ActiveRecord nào trong project:

@user.decorate.full_name
User.first.decorate.full_name

Vậy là xong, có thể thấy Draper cũng khá dễ hiểu và dễ sử dụng. Ngoài ra Draper cũng cung cấp khá nhiều method khác linh hoạt và mạnh mẽ, hỗ trợ cho chúng ta.

Tham khảo

Trên đây là một vài chia sẻ của mình về Decorator trong Rails, cảm ơn các bạn đã dành thời gian đọc bài viết. Các bạn cũng có thể tìm hiểu thêm tại: https://github.com/amatsuda/active_decorator https://github.com/drapergem/draper https://gorails.com/episodes/decorators-with-draper


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí