almost 4 years ago

這一篇的重點是除了 Helper 和 Partial 外,還有什麼工具是可以拿來用來整理 View 的。

11. content_for ( yield )

有些開發者不是很了解 Rails 的 yield 是拿來作什麼的。你可以理解成 跳躍到定點執行

這招常被用在一個情景上: Best Practices for Speeding Up Your Web Site 中的 put javascript at bottom。

在調整前端 performance 時,最常見也最有效的一招就是,把肥大的 JavaScript 放在最底端讀入執行,因為很多 JS 都是 document.ready 才會被執行。

但是,如果開發者只是把 javascript_include_tag 丟到 view 的底下,如:

<%= stylesheet_link_tag "application" %>
  <%= yield %>
<%= javascript_include_tag "application" %>

其實這樣有時候是不會動的,因為當你的 View 裡面需要寫 inline javascripts 時,如:

   your content stuff 
   
   <script type= "text/javascript">
     your script here
   </script>

會得到 javascript undefined。

這通常是因為 inline javascripts 呼叫了 jQuery 裡面的函式,而 inline javascripts 被執行的比 jQuery 被讀入的時間早,所以會出現 undefined。

所以你只好被迫將優美的

<%= stylesheet_link_tag "application" %>
  <%= yield %>
<%= javascript_include_tag "application" %>

改回

<%= stylesheet_link_tag "application" %>
    <%= javascript_include_tag "application" %>
<%= yield %>

其實要解決這樣的問題。只需要把 View 改成這樣:

<%= stylesheet_link_tag "application" %>
  <%= yield %>
<%= javascript_include_tag "application" %>
  <%= yield :page_specific_javascript %>  

需要插入 inline javascripts 的地方再這樣寫,這樣 inline javascripts 就會在正確的位置 page_specific_javascript 被執行。

   your content stuff 
   
   <%= content_for :page_specific_javascript do %>
     <script type= "text/javascript">
       your script here
     </script> 
   <% end %>

套用在 sidebar 上

這招也可以用在 sidebar 上。很多內容網站裡面常常需要放置側邊欄廣告,而這些網站通常有嚴重的 performace issue,原因是它們的 sidebar 都是這樣被設計的:

使用一個全站的 @instance_variable 控制。造成 @instance_variable 到處污染以及 logic in view

<div class="main">
  main content
</div>

<div class="sidebar">
  <% case @ad_type %>
  <% when foo %>
    <%= render "ad/foo"%>
  <% when bar %>
    <%= render "ad/bar"%>    
  <% else %>
    <%= render "ad/default"%>  
  <% end %>
</div>

其實用 yield 就可以巧妙的避開這種問題。將 View 改成

<div class="main">
  <%= yield %>
</div>

<div class="sidebar">
  <%= yield :sidebar %>
</div>

再把各個 view 裡面需要呼叫的 sidebar 拆開獨立呼叫即可

main content

<%= content_for :sidebar do %>
  <%= render "ad/foo"%>
<% end %>

12. Decoration in Controller

有些開發者學到了 yield 這招,就會開始覺得這招實在太棒了,覺得應該可以開始把 Logic 拆散在 View 裡面。如把 meta 定義在 View 裡面:

<%= content_for :meta do %>
  <meta content="xdite's blog" name="description">
  <meta content="Blog.XDite.net" property="og:title">
<% end %>

其實過猶不及也是不好的。如果是關於 meta 的部分,放在 Controller 裡面其實是比較整理和好收納的。反而可以

  • 清楚的標明這個 action 的作用
  • 避免邏輯散落。
  def show
    @blog = current_blog
    drop_blog_title @blog.name
    drop_blog_descption @blog.description
  end
  <%= stylesheet_tag "application" %>
  <%= render_page_title %>
  <%= render_page_descrption %>

13. Decoration using I18n

大家對 Rails 的 I18n 機制的印象都是「作翻譯」,其實 I18n 也可以拿來做 "Decoration"。如:

def render_user_geneder(user)
  if user.gender == "male"
    "男 (Male)"
  else
    "女 (Female)"
  end
end

其實可以被簡化成

def render_user_gender(user)
  I18n.t("users.gender_desc.#{user.geneder}")
end

這樣的情景其實也被可以套用在這種 yes/no ( true/false) 的場景:

def render_book_purchase_option(book)
  if book.aviable_for_purchase?
    "Yes"
  else
    "No"
  end
end

善用 I18n,可以節省不少裝飾用的程式碼。


Maintainable Rails View 系列文目錄

← Maintainable Rails View (2) Maintainable Rails View (4) →
 
comments powered by Disqus