Tạo Decorator đơn giản với Gem Draper và kết hợp cùng Gem Kaminari
Bài đăng này đã không được cập nhật trong 9 năm
1. Decorator là gì ?
Như chúng ta đã biết, Decorator là lớp phụ trợ, là cầu nối giữa Model và View. Hiện tại nó thường được xếp vào dạng “Presenter”. Ưu điểm của Decorator là :
- Thêm những xử lý cho 1 object mà không cần viết thêm những đoạn mã logic thừa thãi trong View và Model.
- Phòng tránh tình trạng phức tạp hoá Helper.
Một ví dụ về Decorator
:
Bạn có một model Article
và một helper
như sau :
# app/helpers/articles_helper.rb
def publication_status article
if article.published?
"Published at #{article.published_at.strftime('%A, %B %e')}"
else
"Unpublished"
end
end
Thay vì việc mỗi lần mỗi lần sử dụng phương thức publication_status
ta phải truyền vào 1 article
ta có thể khai báo publication_status
như là một phương thức của object:
<%= @article.publication_status %>
Nếu không sử dụng Decorator
bạn sẽ phải khai báo publication_status
trong model Article
. Điều này có thể làm cho model của chúng ta trở nên quá nặng nề và khó quản lý. Thay vào đó bạn khai báo trong Decorator
:
# app/decorators/article_decorator.rb
class ArticleDecorator < Draper::Decorator
delegate_all
def publication_status
if published?
"Published at #{published_at}"
else
"Unpublished"
end
end
def published_at
object.published_at.strftime("%A, %B %e")
end
end
Trên view
bạn có thể gọi các phương thức giống hệt như gọi trong model
Bài viết này sẽ hướng dẫn các bạn dùng gem Draper để tạo Decorator một cách đơn giản và kết hợp với gem Kaminari.
2. Cài đặt
- Thêm vào Gemfile:
gem "draper"
- Run
bundle
3. Tạo Decorator
Tạo 1 class Decortor trong thư mục app/decorators
, kế thừa từ Draper::Decorator
và có tên giống với model mong muốn. Ví dụ tạo Decorators cho model Article
class ArticleDecorator < Draper::Decorator
delegate_all
end
Hoặc chạy dòng lệnh :
rails generate decorator Article
khi bạn đã có sẵn model Article, để tạo ArticleDecorator
4. Decorate
Sau khi đã có Decorator, bạn muốn sử dụng các hàm được viết trong đó. Đơn giản bạn chỉ việc gọi phương thức decorate
.
Có 2 trường hợp sử dụng decorate ở đây đó là :
- Sử dụng cho single object :
@article = Article.first.decorate
- Sử dụng cho collection :
@articles = ArticleDecorator.decorate_collection(Article.all)
hoặc nếu collection là một query trả về ActiveRecords
:
@articles = Article.all.decorate
5. Sử dụng Decorator với Kaminari
Khi sử dụng phương thức decorate
sẽ trả về Decorating Objects
trong khi đó nếu bạn sử dụng gem Kaminari để phân trang sẽ không thể hiểu được Decorating Objects
vì scope page
chỉ có thể sử dụng bởi ActiveRecords
.
Có một cách hết sức đơn giản để giải quyết vấn đề đó.
Trước hết bạn tạo 1 class có như sau :
class PaginatingDecorator < Draper::CollectionDecorator
delegate :current_page, :total_pages, :limit_value, :entry_name, :total_count, :offset_value, :last_page?
end
Sau đó trong Decorator mà bạn đã tạo phía trên thêm vào :
def self.collection_decorator_class
PaginatingDecorator
end
Còn đối với gem will paginate thì bạn thay đoạn delegate
trên bằng :
delegate :current_page, :per_page, :offset, :total_entries, :total_pages
Như vậy bạn đã tạo ra 1 Decorator
một cách hết sức đơn giản
Chúc các bạn thành công !!!
All rights reserved