12/08/2018, 13:26

Tìm hiểu gem Draper trong rails

Draper là 1 gem bổ trợ để viết code trông sáng sủa hơn khi bạn viết code với decorator. Bạn hoàn toàn có thể lựa chọn sử dụng hay không sử dụng draper hay decorator trong project của mình nhưng tốt hơn hết là nên sử dụng để đưa project của mình về đúng với bản chất của ruby on rails ( hướng đối ...

Draper là 1 gem bổ trợ để viết code trông sáng sủa hơn khi bạn viết code với decorator. Bạn hoàn toàn có thể lựa chọn sử dụng hay không sử dụng draper hay decorator trong project của mình nhưng tốt hơn hết là nên sử dụng để đưa project của mình về đúng với bản chất của ruby on rails ( hướng đối tượng, dễ đọc dễ hình dung).

Tại sao lại sử dụng decorator?

Tưởng tưởng ứng dụng của bạn có 1 model là Article. trong controller, bạn có method để show bài viết đại khái như sau:

app/controllers/articles_controller.rb

def show
  @article = Article.find(params[:id]).decorate
end

ở trong lớp view, khi bạn muốn sử kiểm tra nếu bài viết này đã được publick thì sẽ in ra ngày tháng năm bài viết được create. còn nếu không thì in ra cụm từ unpublish. Một trong những cách hữu hiệu để xử lí vấn đề này là helper. Đúng, chính xác đó là những điều mình hay làm, đại khái nó sẽ 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

Nhưng hãy tưởng tượng mà xem, viết 1 hàm trong helper để xử lí 1 tác vụ mà chỉ dùng cho model Article thì thật là không hay 1 chút nào. OK, hãy chuyển nó vào model. Mà khoan, chẳng phải như vậy sẽ vi phạm nguyên tắc fat model hay sao.

OK đó là tất cả những lí do mà tôi phải tìm bắt tay vào tìm hiểu gem draper. Bây giờ hãy xem chính xác những gì mà gem này có thể thực hiện. Chúng ta đi tiến hành cài đặt nó.

Cài đặt

Thêm "gem" vào Gemfile:

gem 'draper'

Viết Decorators

Decorators kế thừa từ Draper::Decorator, được đặt trong thư mục app/decorators và được đặt tên theo model mà nó bổ trợ. app/decorators/article_decorator.rb

class ArticleDecorator < Draper::Decorator
...
end

khi bạn đã cài đặt gem và có controller thì bạn sẽ có được 1 decorator với :

rails generate resource Article

nhưng nếu model Article đã tồn tại thì có thể dùng :

rails generate decorator Article

để create ArticleDecorator.

Truy cập Helpers

Tất cả các hàm trong rails helper đều có thể sử dụng trong decorator với object h để gọi ra các hàm trong helper. Nhưng nếu quá lười để viết thêm 1 đoạn 1 kí tự như vậy bạn hoàn toàn có thể add:

include Draper::LazyHelpers

vào trong class để có thể gọi helper như trong view.

Accessing the model

để truy cập vào model trong decorate bạn phải sử dụng từ khóa object. nó cũng tương tự như self vậy

class ArticleDecorator < Draper::Decorator
  def published_at
    object.published_at.strftime("%A, %B %e")
  end
end

Sử dụng decorator với object

Sử dụng trong single object Nếu bạn khai báo

@article = Article.first.decorate

thì object @article sẽ trỏ đến decorator ArticleDecorator và có thể sử dụng thoải mái các method trong đó vì khi khai báo như vậy thì ArticleDecorator đã được inject vào object. Trong trường hợp bạn sử Decorator có tên khác hoặc bạn mướn inject 1 decorator hoàn toàn khác vào đối tượng, bạn có thể khai báo:

@widget = ProductDecorator.new(Widget.first)
 #or, equivalently
@widget = ProductDecorator.decorate(Widget.first)

Collections

nếu bạn có 1 collection của object, bạn có thể inject decorator cho tất cả các object trong đó bằng 1 câu lệnh

@articles = ArticleDecorator.decorate_collection(Article.all)

hoặc

@articles = Article.popular.decorate

cho trường hợp tên model trùng tên decorator.

Chú ý: trong rails 3 .all methods không trả vê 1 query vì thế bạn không thể thực hiện decorate cho colection từ method này, rails 4 dùng bình thường.

Decorating Associated Objects

giả sử như model user có quan hệ với article mà article model lại cũng có decorate riêng của nó thì phải làm như thế nào? Đây là câu trả lời cho bạn:

class UserDecorator < Draper::Decorator
  decorates_association :article
end

Kêt luận

Trên đây tôi đã giới thiệu sơ qua về gem draper. Có thể thấy nó là 1 gem khá hay. Nhưng trên quan điểm của từng người thì nó có ưu điểm và nhược điểm khác nhau. Nếu muốn tìm hiểu kĩ hơn thì có thể tham khảo các link sau.

https://github.com/drapergem/draper

http://thepugautomatic.com/2014/03/draper

http://tutorials.jumpstartlab.com/topics/decorators.html

Hãy cân nhắc nhắc kĩ trước khi dùng 1 gem nào đó. Cảm ơn các bạn đã ghé qua!!!

0