- vừa được xem lúc

[Design Patterns] Presenter và Service objects trong Rails

0 0 88

Người đăng: Lim Kimhuor

Theo Viblo Asia

Bài viết gốc Rails Design Patterns: Presenter & Service Objects

Tại sao chúng ta cần sử dụng design patterns?

Vấn đề đó là cấu trúc của Rails, Model-View-Controller cho thấy kết cấu cơ bản để biết vị trí viết code.

Nhưng vẫn chưa đủ, View sẽ trở nên lớn và đầy logic khi mục đích chung chỉ biểu diễn thông tin.

Trong controller chứa chi tiết ngoài những gì cần làm trong controller theo nhiệm vụ cơ bản của nó.

Giải pháp là gì?

Trong bài viết này có 2 giải pháp cho vấn đề trên dưới dạng design patterns.

  • Sử dụng presenter pattern
  • Sử dụng service object pattern

Không phải ai cũng đồng ý làm sao để thực thi nó nhưng trong bài viết sẽ có bản để có thể hoạt động được. Hãy cùng tìm hiểu các patterns đó.

Sử dụng Presenter trong Rails

các Views để biểu diễn thông tin có nghĩa là các tệp HTML, CSS và ERB(Embedded Ruby). Chú ý rằng không nên có bất kỳ câu truy vấn ActiveRecord trong các views.

Tất cả logic phải loại bỏ từ views nếu muốn nó sạch sẽ và dễ làm việc. (Logic ở đây có nghĩa là các câu lệch if và toán tử ?:

Bây giờ cách giải quyết xử lý logic trong views đó là sử dụng helpers.

Helpers là hữu ích khi chúng ta có một phương định dạng thức toàn cục có thể sử dụng trong một số các views.

Vd: Biểu diễn định dạng markdown, hiển thị ngày tháng với một định dạng nhất định, xóa một số từ cụ thể từ văn bản, vv...

Cách dùng

Chúng ta có thể để code trong thư mục app/helpers và trong tệp date_helper.rb.

module DateHelper def display_date_only_month_year date date.strftime "%B %Y" end
end

Lời khuyên

Hãy luôn đưa đầu vào cho phương thức helpers qua đối số thay vì dựa vào các biến tức thời. Vì cách này sẽ giúp tránh được nhiều rắc rối ?

Phương thức Helpers có giới hạn đặc biệt nếu dùng nó cho tất cả định trong các views. Vì helpers có xu hướng xây dựng và thiếu tính tổ chức.

Thay thế các điều kiện và phương thức định dạng phức tạp

Hãy tưởng tự dạng bạn có một đoạn view như sau

<p> Post title: <%= post.title.gsub "forbidden word", "" %> <%= link_to "Read post", post, class: "w-75 p-3 text-#{post.draft? ? "orange" : "green"} border-#{post.draft? ? "orange" : "green"}" %>
</p>

Đoạn code trên ngắn phải không? nhưng khi đọc code thấy phức tạp với các toán tử và lặp lại code. Bad practice

Hãy tạo một presenter class để giải quyết như sau

class PostPresenter attr_reader :post def initialize post @post = post end def title_without_forbidden_words post.title.gsub "forbidden word", "" end def css_color post.draft? ? "orange" : "green" end
end

Lưu đoạn code trên trong thư mục app/presenters/post_presenter.rb, tạo thư mục presenters nếu chưa có nhé.

<% presenter = PostPresenter.new post %>
<p> Post title: <%= presenter.title_without_forbidden_words %> <%= link_to "Read post", post, class: "w-75 p-3 text-#{presenter.css_color} border-#{presenter.css_color}" %>
</p>

ưu điểm ở đây là:

  • Xóa tất cả logic từ view
  • Đặt tên có nghĩa cho định dạng và các toán tử quyết định.
  • Tái sử dụng class này trong các views khác mà không lặp lại code

Đây là cách mà dùng presenter trong Rails ?

Cách sử dụng các Service Subjects

Trong controller nên chỉ chứa những phần cần làm, chúng không nên chứa về cách làm sao để gửi một Tweet, tính phí khách hàng hoặc tạo tệp PDF.

Các xử lý này nên ủy quyền cho một service object.

Một service object là một Ruby module mà đóng gói logic để hoàn thành một hành vi.

Vd:

module TwitterSerivce def self.send_welcome_message twitter_handle client.update "@{twiter_handle} welcome to 'Dev studio', we hope you enjoy our music!" end def self.client @client ||= Twitter::REST::Client.new do |config| config.consumer_key = "..." config.consumer_secret = "..." config.access_token = "..." config.access_token_secret = "..." end end
end

Để tiện hãy lưu code dưới thư mục app/services và tên tệp twitter_service.rb.

Tại sao phải dùng cách trên? vì Rails autoloads tất cả từ thư mục app/, code trên sẽ sẵn có trong các controllers.

Trong controller chúng ta có thể sử dụng như sau

class UsersController def create TwitterService.send_welcome_message user.twitter_handle end
end

Đây là hành vi của service object.

Kết luận

Trong bài viết đã đưa hai pattern Rails giúp chúng ta cải tiến chất lượng code trong dự án. Hãy áp dụng nó bây giờ.

Cảm ơn các bạn đã đọc ?

Bình luận

Bài viết tương tự

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 3: Docker-compose)

1. Mở đầu. . .

0 0 121

- vừa được xem lúc

Tích hợp VNPAY vào Rails

Xin chào 500 ae năm mới nhé. Tiếp nối câu chuyện về Thanh toán online mà mình có chia sẽ ở 2 bài trước, mọi người chưa đọc thì có thể vào xem ở đây nhé.

1 1 95

- vừa được xem lúc

Tìm hiểu Adapter Pattern trong Rails

. Nếu là một web developer chắc hẳn chúng ta đã không ít lần đọc qua về các Design patterns hay cách áp dụng chúng để làm cho code trở nên hướng đối tượng hơn, dễ đọc, dễ hiểu, dễ maintain, dễ mở rộng, … Các design patterns được áp dụng khá nhiều trong các Rails projects như Service Object, Decorato

0 0 48

- vừa được xem lúc

Sử dụng Searchkick để tìm kiếm thông minh trên Rails và Elasticsearch

Bạn đã bao giờ tự hỏi, ứng dụng web của mình có thể mở rộng quy mô bằng cách học được các từ khóa mà người dùng tìm kiếm? Có giải pháp nào cung cấp công cụ tìm kiếm tự động nhanh chóng với chỉ 1 từ khóa bất kì? Thật may khi có Searchkick và Elasticsearch là các công cụ hỗ trợ công việc tìm kiếm trở

0 0 103

- vừa được xem lúc

Những sai lầm bạn có thể mắc phải khi code Rails

. Chào các bạn, chào các bạn. Đừng vội đóng tab nha.

0 0 47

- vừa được xem lúc

Một số lưu ý cải thiện performance khi làm việc với Rails

Khi làm việc với ruby on rails chắc hẳn chúng ta sẽ làm việc với active record rất nhiều. Tuy nhiên có nhiều điều có thể ta vẫn chưa thực sự hiểu, ví dụ như ActiveRecord execute SQL query như thế nào? Và cũng còn khá nhiều lập trình viên khác cũng không để ý tới điều này.

0 0 111