Rendering Collections in Rails
Bài đăng này đã không được cập nhật trong 7 năm
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
(hiểu đơn giản là không inherit từ ActiveRecord::Base
)
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ệnif..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 %>
Kết luận
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.
Thanks for reading.
All rights reserved