view中好用的小知识

view中好用的小知识

尽量只出现跟前端有关系的东西,不要把判断以及逻辑相关的code放在view。
不好的做法:

1
2
3
4
5
<% if current_user %>
<p><%= current_user.name %></p>
<% else %>
<p>Not Logined</p>
<% end %>

比较好的做法是将if else 改写在partial中,并把current_user.name用helper包起来。这样html code可读性大大提升。

Helper

Helper使用情景:

  • 产生的html code 需要与原始码逻辑混合,但不希望view里面太乱
  • 需要与rails内建的一些方便的helper交叉使用

helper的好处:

  • Don‘t repeat youeself 代码不重复
  • Good Encapsulation 好的封装性
  • 提供view模版良好的组织
  • 易于修改代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module BoardsHelper
# 回傳board的name,避免在view中做太多判斷
def render_board_name(board)
if board.present?
board.name
else
"unknown"
end
end
# 常常重複的區段也可以寫進 helper,統一管理
def render_board_name_path(board)
link_to(board.name, board_path(board))
end
end

在view中可以直接取用如下

1
<%= render_board_name_path(@board) %>

partial

partial 就是代码中的一小段,通常使用在html中,让view的code更干净,将重复的区块切成独立的partial,比如首页,footer,表单,等,让任何页面都能用这段partial,而不用重复写一摸一样的code。

partial使用情景

  • long template 如果html超过两页
  • highly duplicated html内容高度重复
  • independent blocks 可独立作为功能的区块

_topic_list.html.erb

1
2
3
4
5
6
7
<ul>
<% @topics.each do |topic| %>
<li># <%= topic.id %></li>
<li>Topic Name: <%= link_to(topic.title, topic_path(topic)) %></li>
<li>Description: <%= topic.content %></li>
<% end %>
</ul>

index.html.erb

1
2
3
...
<%= render "topic_list" %>
...

collection partial

上例可以改写
_topic_list.html.erb

1
2
3
<li># <%= topic.id %></li>
<li>Topic Name: <%= link_to(topic.title, topic_path(topic)) %></li>
<li>Description: <%= topic.content %></li>

index.html.erb

1
2
3
...
<ul><%= render :partial => "topic_list", :collection => @topics, :as => :topic %></ul>
...

partial&helper

partial 复杂处理大段html code或是之后利用ajax render出来的片段

helper则负责跟逻辑判断有关的东西

比如:
topics_helper.rb

1
2
3
4
5
module TopicsHelper
# 需要邏輯判斷的工作留給helper
def render_published_topic_name_path(topic)
link_to(topic.name, topic_path(topic)) if topic.is_published?
end

_topic_info.html.erb

1
2
3
4
5
6
7
8
9
10
11
12
13
# partial只需要負責html的部分
<table>
<thead>
<tr>
<td>Topic name</td>
</tr>
</thead>
<tbody>
<tr>
<td><%= render_published_topic_name_path(topic) %></td>
</tr>
</tbody>
<table>

yiled in view

yield就是会被替换成样板的地方,基本上所有的html.erb最后都会显示在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这样的好处是将网站版型固定。只需要在出现内容的地方用yield引进即可。
application.html.erb
```ruby
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<div class="container">
# erb檔案就是被引入這裡
<%= yield %>
</div>
#可以指定要yield哪個區塊
<%= yield(:javascripts) %>
</body>
</html>

还可以用content_for让content替换掉

1
2
3
4
5
```ruby
<%= content_for :javascripts do %>
#content here
<% end %>

Nested form

1
2
3
4
5
class Product < ActiveRecord
has_many :specs, :dependent => :destroy
accepts_nested_attributes_for :specs
end
1
2
3
class Spec < ActiveRecord
belongs_to :product
end

view/admin/products/_form.html.erb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%= simple_form_for [:admin, @product] do |f| %>
<%= f.input :name, :required => true %>
<%= f.input :description, :required => true %>
<%= f.input :price %>
<!-- nested form從這裡開始 -->
<%= f.simple_fields_for :specs do |spec| %>
<%= spec.input :name %> <!-- spec的name欄位 -->
<%= spec.input :detail %> <!-- spec的detail欄位 -->
<% end %>
<!-- nested form結束 -->
<%= f.button :submit, "Submit", :disable_with => "Submiting..." %>
<% end %>