Decorator in Rails
Bài đăng này đã không được cập nhật trong 6 năm
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ệuView
nhận trách nhiệm hiển thị dữ liệuController
là nơi trung gian điều phối dữ liệu, cầu nối giữamodel
vàview
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ộtpattern
, có vai trò là cầu nối giữamodel
vàview
. 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_name
và last_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