rails模板佈局學習筆記

一、如何渲染
1、如有以下控制器
[code]
BooksController
def show
@book = Book.find(params[:id])
end
end
[/code]
Rails將自動渲染 app/views/books/show.html.erb

2、事實上,如果你設置了捕獲所有路由 map.connetc ':controller/:action/:id',
Rails將自動渲染views,即使在controller裏面你沒有寫任何代碼。

3、真正渲染頁面的類是:ActionView::TemplateHandlers

4、反饋一個空的結果給瀏覽器
render :nothing => true

5、render_to_string 渲染字符串(最直接的方式)

6、使用相同controller下的別的action的模板來渲染
以下渲染edit.html.erb模板的方式,不會執行edit action裏的代碼,
因此模板裏調用的實例變量,都必須在渲染前賦值好
[code]
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
redirect_to(@book)
else
render "edit"
#render :edit
#render :action => "edit" #舊的方式
end
end
[/code]

7、使用不同controller下的某個action的模板來渲染
render 'products/show'
render :template => 'products/show' #舊的方式

8、渲染任意的文件
默認情況下,渲染任意文件不會使用當前layout,
如果想使用當前layout,加上:layout => true
render "/u/apps/warehouse_app/current/app/views/products/show"
#舊的方式
render :file => "/u/apps/warehouse_app/current/app/views/products/show"

9、在controller內inline渲染(字符串模板)
render :inline => "<% products.each do |p| %><p><%= p.name %></p><% end %>"
默認情況下,inline渲染使用ERB,但你可強制使用Builder
render :inline => "xml.p {'Horrid coding practice!'}", :tpye => :builder

10、渲染文本
默認情況下,渲染文件不會使用當前layout,如有需要,加上 :layout => true。
render :text => "OK"

11、渲染JSON
不需要@product.to_json,render會自動調用該方法
render :json => @product

12、渲染XML
render :xml => @product

13、渲染選項 Options

:content_type
render :file => filename, :content_type => 'application/rss'

:layout
render :layout => 'special_layout'
render :layout => false

:status
render :status => 500
render :status => :forbidden #被禁止的

可以在actionpack/lib/action_controller/status_codes.rb文件裏找到symbol和
status的對映

:location
render :xml => photo, :location => photo_url(photo)

14、尋找layout
Rails首先會在app/views/layouts目錄下查找與controller同名的layout文件,
如果沒有找到,則會使用app/views/layouts/application.html.erb
或app/views/layouts/application.builder。
除以上文件都外,Rails還提供多種方式來選擇layout

爲controller指定layout,替換默認的layout
Class ProductsController < ApplicationController
layout "inventory"
#...
end

指定一個全局的layout
class ApplicationController < ActionController::Base
layout "main"
#...
end

在運行時中指定layout(動態的layout)
Class ProductsController < ApplicationController
layout :products_layout

def show
@product = Product.find(params[:id])
end

private
def products_layout
@current_user.special? ? "special" : "products"
end
end


class ProductsController < ApplicationController
layout proc { |controller| controller.request.xhr? ? 'popup' : 'application' }
# ...
end

帶條件的layout設置
除index和rss這兩個action之外,其餘action都使用名爲product的layout
rss這個layout只有rss這個action使用
class ProductsController < ApplicationController
layout "product", :except => [:index, :rss]
layout "rss", :only => :rss
#...
end

layout繼承
ApplicationController的layout設置 <-- Controller的layout設置 <-- render方法的layout選項
本地的設置會覆蓋父級的設置,如果本級無設置,則繼承父級的設置

15、避免重複渲染
def show
@book = Book.find(params[:id])
if @book.special?
render :action => "special_show" and return
end
render :action => "regular_show"
end

16、使用跳轉redirect_to
redirect_to給瀏覽器的響應是:告訴瀏覽器發起一個新的請求

redirect_to photos_path

redirect_to :back

redirect_to photos_path, :status => 301 #301臨時跳轉
redirect_to photos_path, :status => 302 #302永久跳轉

17、redirect_to和render的區別
render渲染用戶指定的模板作爲響應
redirect_to會結束當前響應,並告訴瀏覽器請求一個新的url

18、響應時只返回HTTP header
head :bad_request
head :created, :location => photo_path(@photo)


二、結構化佈局

1、資源標記Asset Tags
auto_discovery_link_tag
javascript_include_tag
stylesheet_link_tag
image_tag

<%= auto_discovery_link_tag(:rss, {:action => “feed”}, {:title => “RSS Feed”} %>
<%= javascript_include_tag "main", "/photos/columns" %>

緩存腳本
<%= javascript_include_tag "main", "columns", :cache => true %>

緩存css
<%= stylesheet_link_tag "main", "columns", :cache => true %>

Img標記
<%= image_tag "icons/delete.gif", :height => 45 %>

2、理解yield和content_for
<html>
<head>
<%= yield :head %>
</head>
<body>
<%= yield %>
</body>
</html>

<% content_for :head do %>
<title>A simple page</title>
<% end %>
<p>Hello, Rails!</p>

3、使用partials
渲染模板同級目錄下的_menu.html.erb
<%= render :partial => "menu" %>

渲染app/views/shared/_menu.html.erb
<%= render :partial => "shared/menu" %>

4、爲partial指定layout
<%= render :partial => "link_area", :layout => "graybar" %>

5、渲染partial時傳遞局部變量
view模板文件
<%= render :partial => "form", :locals => { :button_label => "Create zone", :zone => @zone } %>

partial模板文件
<% form_for(zone) do |f| %>
<p>
<b>Zone name</b><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.submit button_label %>
</p>
<% end %>

6、每一個partial擁有一個和文件名相同的默認局部變量(不包括_)
如_customer.html.erb擁有customerp這個默認局部變量

<%= render :partial => "customer", :object => @new_customer %>

使用:object選項傳遞變量時,變量將會傳遞給partial的默認變量

7、渲染集合
index.html.erb
<h1>Products</h1>
<%= render :partial => "product", :collection => @products %>

_product.html.erb
<p>Product Name: <%= product.name %></p>

@products的每一個product都會渲染一次_product.html.erb,
如果:collection選項指定的變量爲partial中引用變量的複數形式,
那麼渲染時自動傳遞集合變量的成員給partail
如果不符合這條慣例,則需要加:as選項指定
<%= render :partial => "product", :collection => @products, :as => :item %>

8、集合計數器
rails在渲染partial傳遞集合時,會傳遞一個集合計數器給partial
如傳遞@products,那麼也將傳遞給product_counter給partial,
告訴你多少個partail已經被渲染了

9、渲染集合時使用間隔模板
以下代碼會使用_product模板渲染每一個product後,渲染_product_ruler模板
<%= render :partial => "product", :collection => @products, :spacer_template => "product_ruler" %>


10、嵌套佈局
Using Nested Layouts

You may find that your application requires a layout that differs slightly from your regular application layout to support one particular controller. Rather than repeating the main layout and editing it, you can accomplish this by using nested layouts (sometimes called sub-templates). Here’s an example:

Suppose you have the follow ApplicationController layout:

* app/views/layouts/application.html.erb

<html> <head> <title><%= @page_title or 'Page Title' %></title> <%= stylesheet_link_tag 'layout' %> <style type="text/css"><%= yield :stylesheets %></style> </head> <body> <div id="top_menu">Top menu items here</div> <div id="menu">Menu items here</div> <div id="content"><%= yield(:content) or yield %></div> </body> </html>

On pages generated by NewsController, you want to hide the top menu and add a right menu:

* app/views/layouts/news.html.erb

<% content_for :stylesheets do %> #top_menu {display: none} #right_menu {float: right; background-color: yellow; color: black} <% end -%> <% content_for :content do %> <div id="right_menu">Right menu items here</div> <%= yield(:news_content) or yield %> <% end -%> <% render :file => 'layouts/application' %>

That’s it. The News views will use the new layout, hiding the top menu and adding a new right menu inside the “content” div.

There are several ways of getting similar results with different sub-templating schemes using this technique. Note that there is no limit in nesting levels. One can use the ActionView::render method via render :file => 'layouts/news' to base a new layout on the News layout. If one is sure she will not subtemplate the News layout, she can ommit the yield(:news_content) or part.
發佈了24 篇原創文章 · 獲贊 0 · 訪問量 2774
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章