Tạo Decorator đơn giản với Gem Draper và kết hợp cùng Gem Kaminari
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. ...
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 !!!