Action 視圖部分
還有一個方便的方法可以在當前控制器中呈現子範本,它取決於單一物件(我們稱這種子範本為部分)。它依賴於部分應該遵循命名前綴為底線的命名慣例,以將它們與可以自行呈現的常規範本區分開。
在 Advertiser#account 的範本中
<%= render partial: "account" %>
這會呈現「advertiser/_account.html.erb」。
在 Advertiser#buy 的另一個範本中,我們可以使用
<%= render partial: "account", locals: { account: @buyer } %>
<% @advertisements.each do |ad| %>
<%= render partial: "ad", locals: { ad: ad } %>
<% end %>
這會先使用傳入的 @buyer 呈現為區域變數 account,再呈現 advertiser/_ad.html.erb 並將 ad 區域變數傳遞給範本以顯示。
:as 和:object 選項
預設 ActionView::PartialRenderer
沒有任何區域變數。可以使用 :object
選項將物件傳遞至部分。例如
<%= render partial: "account", object: @buyer %>
會將 @buyer 物件提供給部分,可透過區域變數 account 使用,並相當於
<%= render partial: "account", locals: { account: @buyer } %>
使用 :as
選項,我們可以為區域變數指定其他名稱。例如,如果我們希望使用 user 而非 account,我們會執行
<%= render partial: "account", object: @buyer, as: 'user' %>
這相當於
<%= render partial: "account", locals: { user: @buyer } %>
呈現部分集合
使用部分的範例說明了一個常見的模式,其中範本需要反覆運算陣列並為每個元素呈現子範本。此模式已實作為單一方法,它接受陣列並呈現與包含元素同名的部分。因此,可以在「使用部分」中的三行範例使用單一行來改寫
<%= render partial: "ad", collection: @advertisements %>
這會呈現 advertiser/_ad.html.erb
並將 ad 區域變數傳遞給範本以顯示。會自動提供反覆運算物件給範本,名稱格式為 partial_name_iteration
。反覆運算物件知道目前的物件在集合中的索引和集合的總大小。反覆運算物件也有兩個方便的方法,first?
和 last?
。以上面的範例來說,範本會提供 ad_iteration
。為了向後相容性,partial_name_counter
仍然存在,並會對應到反覆運算的 index
方法。
在呈現部分時可以使用 :as
選項。
您可以透過 :spacer_template
選項指定在元素之間要呈現的部分。下面範例會在每個廣告部分之間呈現 advertiser/_ad_divider.html.erb
<%= render partial: "ad", collection: @advertisements, spacer_template: "ad_divider" %>
如果指定的 :collection
為 nil
或空白,render
會傳回 nil
。這會讓您可以指定文字,並使用下列格式來顯示
<%= render(partial: "ad", collection: @advertisements) || "There's no ad to be displayed" %>
呈現共用部分
兩個控制器可以共用一組部分並按照以下方式呈現它們
<%= render partial: "advertisement/ad", locals: { ad: @advertisement } %>
這會呈現部分 advertisement/_ad.html.erb
,而不論從哪個控制器呼叫。
呈現會回應 to_partial_path 的物件
您可以讓 PartialRenderer
執行工作並檢查 to_partial_path
方法來選擇適當路徑,而不是明確命名部分的位置。
# @account.to_partial_path returns 'accounts/account', so it can be used to replace:
# <%= render partial: "accounts/account", locals: { account: @account} %>
<%= render partial: @account %>
# @posts is an array of Post instances, so every post record returns 'posts/post' on +to_partial_path+,
# that's why we can replace:
# <%= render partial: "posts/post", collection: @posts %>
<%= render partial: @posts %>
呈現預設情況
如果你不打算使用任何集合或版面選項,也可以使用簡寫的 render 預設值來呈現部分畫面。範例
# Instead of <%= render partial: "account" %>
<%= render "account" %>
# Instead of <%= render partial: "account", locals: { account: @buyer } %>
<%= render "account", account: @buyer %>
# @account.to_partial_path returns 'accounts/account', so it can be used to replace:
# <%= render partial: "accounts/account", locals: { account: @account} %>
<%= render @account %>
# @posts is an array of Post instances, so every post record returns 'posts/post' on +to_partial_path+,
# that's why we can replace:
# <%= render partial: "posts/post", collection: @posts %>
<%= render @posts %>
用版面呈現部分畫面
部分畫面可以套用自己的版面。這些版面不同於針對整個動作設定的全局版面,但運作方式類似。假設有一個清單,其中包含兩種使用者
<%# app/views/users/index.html.erb %>
Here's the administrator:
<%= render partial: "user", layout: "administrator", locals: { user: administrator } %>
Here's the editor:
<%= render partial: "user", layout: "editor", locals: { user: editor } %>
<%# app/views/users/_user.html.erb %>
Name: <%= user.name %>
<%# app/views/users/_administrator.html.erb %>
<div id="administrator">
Budget: $<%= user.budget %>
<%= yield %>
</div>
<%# app/views/users/_editor.html.erb %>
<div id="editor">
Deadline: <%= user.deadline %>
<%= yield %>
</div>
…將會回傳
Here's the administrator:
<div id="administrator">
Budget: $<%= user.budget %>
Name: <%= user.name %>
</div>
Here's the editor:
<div id="editor">
Deadline: <%= user.deadline %>
Name: <%= user.name %>
</div>
如果提供了一個集合,版面會為集合中的每個項目呈現一次。例如,這兩個程式片段的輸出相同
<%# app/views/users/_user.html.erb %>
Name: <%= user.name %>
<%# app/views/users/index.html.erb %>
<%# This does not use layouts %>
<ul>
<% users.each do |user| -%>
<li>
<%= render partial: "user", locals: { user: user } %>
</li>
<% end -%>
</ul>
<%# app/views/users/_li_layout.html.erb %>
<li>
<%= yield %>
</li>
<%# app/views/users/index.html.erb %>
<ul>
<%= render partial: "user", layout: "li_layout", collection: users %>
</ul>
假設有兩個使用者的名字分別為 Alice 和 Bob,這些程式片段會回傳
<ul>
<li>
Name: Alice
</li>
<li>
Name: Bob
</li>
</ul>
正在呈現的目前物件和 object_counter,將會在版面範本中作為本地變數,其名稱與部分畫面中可用的名稱相同。
你也可以將版面套用至任何範本中的區塊
<%# app/views/users/_chief.html.erb %>
<%= render(layout: "administrator", locals: { user: chief }) do %>
Title: <%= chief.title %>
<% end %>
…將會回傳
<div id="administrator">
Budget: $<%= user.budget %>
Title: <%= chief.name %>
</div>
正如你所見,:locals
雜湊同時在部分畫面和其版面之間共用。
類別公用方法
new(lookup_context, options) 連結
原始碼:顯示 | 在 GitHub 上
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 223 def initialize(lookup_context, options) super(lookup_context) @options = options @locals = @options[:locals] || {} @details = extract_details(@options) end
實例公用方法
render(partial, context, block) 連結
原始碼:顯示 | 在 GitHub 上
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 230 def render(partial, context, block) template = find_template(partial, template_keys(partial)) if !block && (layout = @options[:layout]) layout = find_template(layout.to_s, template_keys(partial)) end render_partial_template(context, @locals, template, layout, block) end