Rendering Collections in Rails
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 ...
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.
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.
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 %>
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 %>
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.