Refactor ruby on rails 2

Refactor view

Trong bài viết Refactor ruby on rails chúng ta đã tìm hiểu một số cách refactor code, hôm nay chúng ta sẽ tìm hiểu kỹ hơn về Refactor view

Refactor view

1. Tìm hiểu về yield

  • Đây là đoạn code khá quen thuộc trong app/views/layouts/application.html.erb

<html>
  <head>
  <%= yield :head %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>

Khi render ra 1 action view nào đó, mặc định nó sẽ được sử dụng layout "application", bạn có thể tạo thêm 1 số layout khác nếu muốn nhưng tốt nhất nên hạn chế điều đó. Đoạn code được viết trong view app/views/users/show.html.erb sẽ được fill vào <%= yield %>

<div class="col-md-3">
  <%= "Hello" %>
</div>
<div class="col-md-9">
  <%= "World" %>
</div>

Kết quả, ta có html _book.html.erb


<html>
  <head>
  </head>
  <body>
    <div class="col-md-3">Hello</div>
    <div class="col-md-9">World</div>
  </body>
</html>

2. Tìm hiểu về content_for

  • chẳng hạn, nếu ta cung cấp nội dung cho <%= yield :head %>

<% content_for :head do %>
  <title>A simple page</title>
<% end %>

<p>Hello, Rails!</p>

Kết quả thu được

<html>
  <head>
  <title>A simple page</title>
  </head>
  <body>
  <p>Hello, Rails!</p>
  </body>
</html>

Nghe chừng có vẻ đơn giản nhưng điều này rất hữu ích và linh hoạt khi mỗi trang ta muốn set 1 title riêng. Chỉ cần tay nội dung bên trong content_for :head là được, trang nào không sử dụng thì ko viết content_for :head.

  • Bạn cũng có thể sử dụng yield cho partial search_filters.html.erb, search_filters.html.erb được dùng như là 1 layout.

<%= render "shared/search_filters", search: @q do |f| %>
  <p>
    Name contains: <%= f.text_field :name_contains %>
  </p>
<% end %>

<%= render "shared/search_filters", search: @q do |f| %>
  <p>
    Title contains: <%= f.text_field :title_contains %>
  </p>
<% end %>

shared/_search_filters.html.erb


<%= form_for(@q) do |f| %>
  <h1>Search form:</h1>
  <fieldset>
    <%= yield f %>
  </fieldset>
  <p>
    <%= f.submit "Search" %>
  </p>
<% end %>

3. Tìm hiểu về provide

<% content_for :head do %>
  <title>A simple page</title>
<% end %>
<% content_for :head do %>
  <title>xxx</title>
<% end %>
<p>Hello, Rails!</p>
<% provide :head do %>
  <title>A simple page</title>
<% end %>
<% provide :head do %>
  <title>xxx</title>
<% end %>
<p>Hello, Rails!</p>

provide không khác gì content_for nhưng nếu provide thì html thu được cũng chỉ in ra 1 lần (provide cuối cùng) <%= yield :head %> , còn content_for sẽ được in ra tất cả (giống như mảng) content_for Khá hữu ích nếu như có 1 vài script tag bạn chỉ muốn sử dụng ở 1 vài trang

<%= javascript_include_tag "http://example.com/main.js" %>

4. Local Variables

<%= render partial: "product", collection: @products,
  as: :item, locals: {number: Random.rand()} %>

Mỗi lần render partial: "product" sẽ có biến local number giá trị khác nhau, rails cũng tự tạo ra biến product_counter ("#{file_name}_counter") có giá trị index của item hiện tại trong mảng. Hoặc các biến product_iteration.index, product_iteration.last?... rất tiên lợi khi ghép giao diện.

Ban cũng có thể sử dụng local_assigns để chỉnh lại 1 partial đã đang được sử dụng mà ko muốn làm ảnh hưởng đến những phần đang hoạt động. Chẳng hạn partial này có 2 style là full textshort text. Có thể reuse code như sau:

_article.html.erb


<h2><%= article.title %></h2>

<% if local_assigns[:full] %>
  <%= simple_format article.body %>
<% else %>
  <%= truncate article.body %>
<% end %>

index.html.erb

<%= render user.articles %>

show.html.erb


<%= render article, full: true %>

Tổng kết

Như vậy chúng ta đã có thể sử dụng yield, content_for, localassigns để render view 1 cách linh hoạt

Tài liệu tham khảo

http://guides.rubyonrails.org/layouts_and_rendering.html#understanding-yield