本章的作業目標:
- 使用系統 helper 整理 code
- 自己撰寫的 helper 包裝 html
- 使用 partial 整理 html
- 使用 scope 整理 query
使用系統 helper 整理 code
時間格式
我們會發現在時間格式上是顯示
2014-07-19 08:02:17 UTC
我們可以改用這樣的寫法:
...
...
<td> <%= post.updated_at.to_s(:long) %> </td>
...
...
or
...
...
<td> <%= post.updated_at.to_s(:short) %> </td>
...
...
內文自動斷行
要讓 post 的 content 能自動斷行
...
...
- <td> <%= post.content %> </td>
+ <td> <%= simple_format(post.content) %> </td>
...
...
如果後台的 account/post 也要改的話,
一樣打開 app/views/account/posts/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
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 拆分
讓檔案看起來乾淨清爽
使用前
<!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>
使用後
<!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
<%= 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 這二個檔案修改
...
..
- <%= 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
在上一章我們在設計了一行程式碼,
讓文章永遠按照最新的時間降序排列
...
...
def index
@posts = current_user.posts.order("updated_at DESC")
end
...
...
.order("updated_at DESC")
其實是一段可能會很常用到的程式碼
既然能在 View 裡面用 helper 跟 partial 整理
在 controller 當然也能用 scope 整理
class Post < ActiveRecord::Base
+ scope :recent, -> { order("updated_at DESC") }
...
...
有需要用 最新 -> 最舊 排序的 controller 就直接改放 .recent 即可
...
...
def index
- @posts = current_user.posts
+ @posts = current_user.posts.recent
end
...
...