`

Layout in Rails

阅读更多
参考链接:http://guides.rubyonrails.org/layouts_and_rendering.html#structuring-layouts

layout

layout最基本的使用很简单,默认的layout是app/views/layout目录里与controller同名的模板。如果要指定为其它布局,可以在controller里调用layout方法,像这样:
class ProductsController < ApplicationController 
 layout "inventory"
 #....
end

之后,所有的action都将以app/views/layout/inventory.html.erb为布局来渲染模板。layout方法还支持:except:only两个选项,用来选择layout方法影响到的action,顾名思义吧,不记了。
layout "product", :except => [:index, :rss] 

动态布局
当layout方法的参数为一个symbol的时候,这个controller的布局是动态的,必须在controller里定义一个与symbol对应的方法(一般为private即可),这个方法必须返回一个字符串,用作指定布局的名字:
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 


结构化布局(Structuring Layouts)

Asset Tags

javascript_include_tag
在页面中引入js文件:public/javascripts/main.js:
<%= javascript_include_tag "main" %>

引入public/javascripts/main.js 和 public/javascripts/columns.js:
<%= javascript_include_tag "main", "columns" %>

引入public/javascripts/main.js 和 public/photos/columns.js:
<%= javascript_include_tag "main", "/photos/columns" %>

引入http://example.com/main.js:
<%= javascript_include_tag "http://example.com/main.js" %>

:defaults 选项可用于引入Prototype 和 Scriptaculous 库:
<%= javascript_include_tag :defaults %>

:all 选项加载public/javascripts目录下的每个js文件, 以Prototype 和 Scriptaculous开头:
<%= javascript_include_tag :all %> 

:recursive 选项用于指定是否包含public/javascripts目录的子目录中的js文件:
<%= javascript_include_tag :all, :recursive => true %>

如果你加载了多个js文件,可以通过设置:catch选项为true来组合多个js文件到一个js文件中,从而增强用户体验。 :
<%= javascript_include_tag "main", "columns", :cache => true %>

默认的,这些js文件将被组合到javascripts/all.js中。你可以手动指定一个缓存文件的位置:
<%= javascript_include_tag "main", "columns", :cache => 'cache/main/display' %>

甚至可以使用动态的路径,像这样:cache/#{current_site}/main/display.

stylesheet_link_tag

stylesheet_link_tag的使用大致和javascript_include_tag相同,只是没有那个:defaults选项。另外,stylesheet_link_tag多了:media、:rel和:type三个选项,用于指定stylesheet link的media、rel和type值,默认值为:media="screen" rel="stylesheet" type="text/css"。

layout中的yield

在layout里面,yield用来标识view应该插入的地方。像这样:
<html> 
 <head> 
 </head> 
 <body> 
 <%= yield %> 
 </body> 
</html> 

带参数的yield一般与content_for一起使用:
<!--layout-->
<html> 
 <head> 
 <%= yield :head %> 
 </head> 
 <body>
  <%= yield %> 
 </body> 
</html> 
<!--view-->
<% content_for :head do %> 
 <title>A simple page</title> 
<% end %> 
<p>Hello, Rails!</p> 
<!--结果-->
<html> 
 <head>
  <title>A simple page</title> 
 </head> 
 <body>
  <p>Hello, Rails!</p> 
 </body> 
</html> 

partial

把partial作为view的一部分来渲染,可以调用render方法:
<%=render :partial=>"menu"%>

上面的代码会把文件名为_menu.html.erb的模板渲染到当前模板中。
<%= render :partial => "shared/menu" %> 

渲染app/views/shared/_menu.html.erb到当前模板。
可以为partial单独指定layout:
<%= render :partial => "link_area", :layout => "graybar" %> 

partial的layout文件名必须以下划线开头:_graybar.html.erb,而且必须把layout模板文件和partial放在同一个目录下。

给partial传递局部变量
:locals选项用于设置partial的局部变量:
<%= render :partial => "form", :locals => { :button_label => "Create zone", :zone => @zone } %> 

这样就可以在_form.html.erb中访问button_label和zone这两个变量。

每个partial都有一个和partial名字相同(不带下划线)的局部变量,可以通过:object选项给这个变量传递值:
<%= render :partial => "customer", :object => @new_customer %> 

这样就可以在_customer.html.erb中访问customer这个变量,它指向@new_customer。

当然,作为父模板(parent)的一部分,partial可以直接访问父模板的实例变量,例如这里的@new_customer,但是如果这么做的话,partial就跟父模板耦合了,变得不容易重用了。所以建议使用partial的名字来引用实例变量而不是直接访问实例变量。
之前版本的Rails中,如果不指定:object或者:locals选项,rails会自动在父模板中寻找与partial同名的那个实例变量作为partial的局部变量,如:
<%= render :partial => "customer" %> 

如果在_customer.html.erb中访问customer这个变量,rails将会自动在父模板中寻找名为@customer的实例变量。这个特性在Rails2.2中已经不建议使用了(deprecated)。Rails3.0中已经将这个特性移除了。

如果要传递给partial的实例变量名==partial名==model名,可以简写,如:
#当@customer为Customer这个model的实例,并且partial名为customer时
<%= render :partial => @customer %> 
#相当于
<%= render :partial => "customer", :object=>@customer %> 


渲染集合(Collections)
:collection选项用于指定被传递给partial的集合对象,假设有books这么个集合,包含了5个Book对象,可以这样使用:
#main.html.erb
<%= render :partial => "book", :collection => books %>
#_book.html.erb
<p><%= book.name%></p>

这样,在main.html.erb中,_book.html.erb的内容会被渲染5次。这时候,partial模板中,与partial同名的那个变量指向了:collection选项传过来的集合中的每一项。如果你不想使用这个与partial同名的变量名,可以通过:as选项来设置你想要的变量名(:as的值只能用symbol,不能是string,否则在partial里会得到nil值):
<%= render :partial => "product", :collection => @products, :as => :item %> 

在设置:collection选项的时候,rails同时提供了一个counter变量给partial模板,变量名以partial名(不带下划线)开头,以_counter结尾,并且经试验,这个变量名不受:as选项影响(也就是说在上面的代码中,这个变量名应该是product_counter而不是item_counter)。其值为collection对象的索引值(从0开始)。
:spacer_template选项用于指定填充于collection每个member之间的模板:
<%= render :partial => "product", :collection => @products, :spacer_template => "product_ruler" %> 

上面的代码中,_product_ruler.html.erb的内容将被填充到每一对_product partial之间。
和:object一样,:collection也有简写形式:
<%= render :partial => @products %> 
分享到:
评论
2 楼 yuan 2010-08-19  
星情泪 写道
非常好的整理。

顺便问一下楼主,有没有遇到过这样的情况,当
<%= render :partal => 'post/bar' %>

的时候,rails没有找post/_bar.html.erb却直接找post/_bar.erb了?

好像如果_bar.html.erb不存在,但_bar.erb存在的话,rails是会找到_bar.erb的。
如果两者都不存在,rails的提示好像也是_bar.erb不存在之类的信息。
1 楼 星情泪 2010-08-19  
非常好的整理。

顺便问一下楼主,有没有遇到过这样的情况,当
<%= render :partal => 'post/bar' %>

的时候,rails没有找post/_bar.html.erb却直接找post/_bar.erb了?

相关推荐

    Enterprise Rails

    * Tour an ideal enterprise systems layout: how Rails fits in, and which elements don't rely on Rails * Learn to structure a Rails 2.0 application for complex websites * Discover how plugins can ...

    rails4_log_watcher:监控日志示例(text、db)

    layout application flow $ rails generate rspec: install 启动服务器$ bundle exec rake db: migrate $ bundle exec rails s ($passenger start) 访问重置宝石见 $ gem uninstall -I -a -x --user-in

    rails_content_issue:对 rails3 content_for 问题的调查

    Find me in app/views/content_test/example.html.erb Content for :[removed] " alert&#40;'hello'&#41;;\n" Content for :javascript2: " alert&#40;'from a render_to_string'&#41;;\n" 导轨 4 导轨 4.1.7 Ruby...

    jQAPI - Alternative jQuery Documentation - For Version 1.7

    *) And it is a fixed layout which means even on my big screen I have to scroll all the way down and have to scan for it. There have to be a better way, obviously. The alternative Rails documentation ...

    rail 4 days

    ### Rails 4 Days 学习指南 #### 引言 Rails 是一款基于 Ruby 的开源 Web 开发框架,因其高效、简洁以及对开发人员友好的特性而受到广泛欢迎。本学习资料将通过四天的时间,带领读者从零开始构建一个完整的 To-Do ...

    arturo:滑轨的功能滑块

    什么 Arturo提供了Rails的功能滑块。 它使您可以像状一样打开和关闭,但可以提供更细粒度的控制。...# in app/views/layout/_sidebar.html.erb: %&gt; &lt;&#37; if_feature_enabled(:live_postings) do %&gt; &lt; h3&gt; Re

    javascript框架介绍

    它提供了一套DOM操作API和事件处理机制,作为核心框架,支撑了一系列的JavaScript扩展库,成为了许多开发者首选的底层框架,尤其是在Ruby on Rails中的广泛应用。Scriptaculous即基于Prototype,用于实现各种JS组件...

    shopify-theme-test

    Liquid 是一种轻量级的、安全的模板语言,由 Ruby on Rails 社区创建,现在广泛应用于 Shopify。它的设计目标是让非程序员也能理解和修改网站模板。以下是一些关于 Liquid 的核心知识点: 1. **变量**:在 Liquid ...

    moonlanders.github.io

    4. **布局技术**:CSS提供了多种布局方式,如流体布局、网格布局(CSS Grid)、Flexbox(弹性盒子)和最近的CSS Layout Module Level 3(CSS 模块布局)。 5. **响应式设计**:使用 `@media` 查询,CSS可以根据设备...

Global site tag (gtag.js) - Google Analytics