over 3 years ago

本章的作業目標:

  • 使用系統 helper 整理 code
  • 自己撰寫的 helper 包裝 html
  • 使用 partial 整理 html
  • 使用 scope 整理 query

使用系統 helper 整理 code

時間格式

我們會發現在時間格式上是顯示

2014-07-19 08:02:17 UTC

我們可以改用這樣的寫法:

app/views/account/posts/index.html.erb
...
...
          <td> <%= post.updated_at.to_s(:long) %> </td> 
...
...

or

app/views/account/posts/index.html.erb
...
...
          <td> <%= post.updated_at.to_s(:short) %> </td> 
...
...

內文自動斷行

要讓 post 的 content 能自動斷行

app/views/groups/show.html.erb
...
...
-         <td> <%= post.content %> </td>
+         <td> <%= simple_format(post.content) %> </td>
...
...

如果後台的 account/post 也要改的話,
一樣打開 app/views/account/posts/index.html.erb
把上述那行改掉

標題文字太長就...

app/views/groups/index.html.erb
...
...
-     <td>  <%= link_to(group.title, group_path(group)) %> </td>
+     <td>  <%= link_to(truncate(group.title, length: 15 ), group_path(group)) %> </td>
...
...


自己撰寫的 helper 包裝 html

在剛剛的專案當中,顯示Post 的程式碼如下:

<%= post.content %> %>

隨著專案變遷,這樣的程式碼,可能會依需求改成:(需要內容斷行)

 <%= simple_format(post.content) %> %>

之後又改成(只顯示頭一百字)

<%= simple_format(truncate(post.content, lenth: 100)) %>

而麻煩的是,這樣類似的內容,常常在專案出現。每當需求變更,開發者就需要去找出來,
有十個地方,就需要改十遍,很是麻煩。

Helper 就是用在這樣的地方

一開始就設計一個 Helper

<%= render_post_content(post) %>  (這是放在 views 裡面的)

然後打開 app/helpers/posts_helper.rb

app/helpers/posts_helper.rb
  def render_post_content(post)
    truncate(simple_format(post.content), lenth: 100)
  end

以後對 @post.content 有任何的異動,只要改 helper 裡的東西就好
不用再到各個有放 @post.content 的檔案一一修改

helper 是全域的變數,即使寫在 posts_helper.rb 裡面
在其他地方像是 groups / account/groups / account/posts
都能呼叫得出來

還有一個好處就是把 view 單純化,把所有運作邏輯全部轉到 helper 裡面
在未來需要維護的時候,會一整個非常乾淨好讀


使用 partial 整理 html

其實我們的 app/views/layout/application.html.erb
就用的 Partial 的用法

把 navbar 跟 footer 拆分

讓檔案看起來乾淨清爽

使用前

app/views/layout/application.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Group101</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<div class="container-fluid">
  <nav class="navbar navbar-default" role="navigation">
    <div class="container-fluid">
      <!-- Brand and toggle get grouped for better mobile display -->
      <div class="navbar-header">
        <a class="navbar-brand" href="/">Rails 101</a>
      </div>

      <!-- Collect the nav links, forms, and other content for toggling -->
      <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
        <ul class="nav navbar-nav navbar-right">
          <% if !current_user %>
          <li> <%= link_to("註冊", new_user_registration_path) %> </li>
          <li> <%= link_to("登入", new_user_session_path) %> </li>
          <% else %>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Hi!, <%= current_user.name %>  
              <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
              <li> <%= link_to("My Groups", account_groups_path) %></li> 
              <li> <%= link_to("My Posts", account_posts_path) %></li> 
              <li> <%= link_to("帳號設定", edit_user_registration_path )%></li>
              <li> <%= link_to("登出", destroy_user_session_path, 
                                 :method => :delete ) %></li>
            </ul>
          </li>
          <% end %>
        </ul>
      </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
  </nav>

  <%= notice_message  %>
  
  <%= yield %>
</div>

<footer class="container" style="margin-top: 100px;">
  <p class="text-center">Copyright ©2014 Rails101s
    <br>Design by <a href="http://sdlong.logdown.com" target=_new>sdlong</a>
  </p>
</footer>

</body>
</html>

使用後

app/views/layout/application.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Group101</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<div class="container-fluid">
  <%= render "common/navbar" %>
  <%= notice_message  %>
  <%= yield %>
</div>
  <%= render "common/footer" %>

</body>
</html>

將 groups/new groups/edit 相同的 form 部分拆成 partial

有沒有發現 groups/new.html.erb 跟 groups/new.html.erb 裡面其實幾乎是一模一樣的?
將二個檔案間共同的 form 拆成 partial 有個好處,未來當要調整欄位的時候,只需要改一個檔案即可

新增 app/views/groups/_form.html.erb
app/views/groups/_form.html.erb
<%= simple_form_for group do |f| %>
  <div class="form-group">
    <%= f.input :title, input_html: { class: "form-control"} %>
    <%= f.input :description, input_html: { class: "form-control"} %>
  </div>
  <%= f.submit "Submit", class: "btn btn-primary", data: { disable_with: "Submitting..." } %>
<% end %>

將 new / edit 這二個檔案修改

app/views/groups/new_html.erb & app/views/groups/edit_html.erb
...
..
- <%= simple_form_for @group do |f| %>
-   <div class="form-group">
-     <%= f.input :title, input_html: { class: "form-control"} %>
-     <%= f.input :description, input_html: { class: "form-control"} %>
-   </div>
-   <%= f.submit "Submit", disable_with: 'Submitting...', class: "btn btn-primary"%>
- <% end %>
+ <%= render "form", group: @group %>
...
...

使用 scope 整理 query

在上一章我們在設計了一行程式碼,
讓文章永遠按照最新的時間降序排列

app/controllers/account/posts_controller.rb
...
...
  def index
    @posts = current_user.posts.order("updated_at DESC")
  end
...
...
.order("updated_at DESC")

其實是一段可能會很常用到的程式碼
既然能在 View 裡面用 helper 跟 partial 整理
在 controller 當然也能用 scope 整理

app/models/post.rb
class Post < ActiveRecord::Base

+ scope :recent, -> { order("updated_at DESC") }
...
...

有需要用 最新 -> 最舊 排序的 controller 就直接改放 .recent 即可

app/controllers/account/posts_controller.rb
...
...
  def index
-   @posts = current_user.posts
+   @posts = current_user.posts.recent
  end
...
...
← [ 2.0 ] 6 - 0. 實做簡單的後台機制 [ 2.0 ] 8. 撰寫 db:seed 與 自動化重整資料庫程式 →
 
comments powered by Disqus