Rendering Collections in Rails
White

namtx viết ngày 22/07/2017

Render partial là một trong những tính năng đem lại sự mãnh mẽ của Rails framework. Nó cung cấp cho chúng ta khả năng tách những view phức tạp thành các phần nhỏ hơn, dễ quản lý hơn, cũng như giữ cho code của chúng ta luôn DRY (Don't Repeat Yourself)
Hẳn ai làm qua Rails cũng dùng từng dòng code như thế này:

<% @cart.products.each do |product| %>
    <%= render partial: "products/product",  locals: {product: product} %>
<% end %>

Tuy nhiên đoạn code dùng với each như trên nhìn rất xấu.

Partial path

Rất may Rails cung cấp cho chúng ta một cách viết ngắn gọn hơn.

<%= render @cart.products %>

Nhìn rất ngắn gọn, dễ đọc, kết quả thì hoàn toàn tương tự. Vậy Rails đã làm điều này như thế nào?
Câu trả lời là function to_partial_path
Hàm này được implement như sau:

# File activemodel/lib/active_model/conversion.rb, line 84
    def to_partial_path
      self.class._to_partial_path
    end

Các model sẽ include ActiveModel::Conversion

class Product
  include ActiveModel::Conversion
end

product = Product.new
product.to_partial_path # => "products/product"

Như vậy ở đoạn code trên:

<%= render @cart.products %>

thì render đã gọi to_partial_path trên từng product để lấy đường dẫn đến file partial dùng cho việc render.

PORO (Plain Old Ruby Object)

to_partial_path cũng được sử dụng với Plain Old Ruby Object

Giả sử chúng ta code class Guest:

class Guest
  def name
    'Guest'
  end

  def to_partial_path
    'users/user'
  end
end

Yêu cầu trong ứng dụng là hiển thị danh sách người dùng, bao gồm guest cũng như registed user đang online trong hệ thống.
Chúng ta có thể sử dụng partial "users/user" cho cả guest lẫn registed user

# home/dashboard.html.erb
<%= render @dashboard.users_online %>
# users/_user.html.erb
<%= user.name %>

Polymorphics

to_partial_path cũng hỗ trợ với Polymorphic.
Giả sử ứng dụng web của chúng ta cho phép người dùng có thể like các bài Post, Comment, hoặc Image của người khác. Ứng dụng yêu cầu hiển thị các post, comments, hay images mà người dùng đã like.
Chúng ta sẽ không cần phải viết từng đoạn code xử lý điều kiện if..else để render cho từng loại Post, Comment hay Image mà chỉ cần viết như sau:

# users/activity_log.html.erb
<h1><%= @user.name %>'s activity log:</h1>
<%= render @user.likes %>
# posts/_post.html.erb
<h1><%= article.name %></h1>
<p><%= article.content %></p>
# comments/_comment.html.erb
<div class="comment">
   <em>Last updated: <%= comment.updated_at %></em>
   <p><%= comment.content %></p>
  </div>
# images/_image.html.erb
<h1><%= image.title %></h1>
  <%= image_tag image.url %>

End

Rails framework cung cấp nhiều magic mang lại nhiều lợi ích trong việc phát triển ứng dụng, tuy nhiên nó cũng làm khó khăn cho những người mới làm quen. Hiểu được những thứ mà mình sử dụng trong framework mình đang sử dụng là một điều rất quan trọng.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

namtx

2 bài viết.
1 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
1 1
Chào mọi người, hôm nay mình viết một bài TIL nhỏ về cách lấy độ phân giải của màn hình hiện tại đang sử dụng. xdpyinfo | grep dimensions Kết quả...
namtx viết 12 tháng trước
1 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
2 bài viết.
1 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!