Layouts and Rendering in Rails
1 Overview: How the Pieces Fit Together
主要在控制器实现这些功能
2 Creating Responses
三种方法:
- Call render to create a full response to send back to the browser
- Call redirect_to to send an HTTP redirect status code to the browser
- Call head to create a response consisting solely of HTTP headers to send back to the browser
2.1 Rendering by Default: Convention Over Configuration in Action
(1)如果在控制器中没有指定任何response,并且也不涉及方法,那么就渲染控制器的index.html.erb,当然路由需要有resource:controller
(2)如果在控制器中没有指定任何response,但涉及某方法则,
Note that again, we have convention over configuration, in that there is no explicit render at the end of this index action. The rule is that if you do not explicitly render something by the end of the controller action, rails will look for the action_name.html.erb template in the controllers view path and then render that,
(3)最后,就是应用用户自定制的上述三种方法,完成Response。本质上,这三者都是通过生成url的形式,实现response,只是处理的细节不一样。
2.2 Using render
You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.
2.2.1 Rendering Nothing
2.2.2 Rendering an Action’s View
render
"edit"
render
:edit
render
:action
=>
"edit" ,
The specified action is used to determine which view to render, but Rails does not run any of the code for that action in the controller. Any instance variables that you require in the view must be set up in the current action before calling render. 这也是render 最主要的特点:不运行该action代码,而是直接渲染视图。
2.2.3 Rendering an Action’s Template from Another Controller
What if you want to render a template from an entirely different controller from the one that contains the action code? You can also do that with render, which accepts the full path (relative toapp/views) of the template to render.
render 'products/show'
2.2.4 Rendering an Arbitrary File
2.2.5 Wrapping it up
render :edit
render :action => :edit
render 'edit'
render 'edit.html.erb'
render :action => 'edit'
render :action => 'edit.html.erb'
render 'books/edit'
render 'books/edit.html.erb'
render :template => 'books/edit'
render :template => 'books/edit.html.erb'
render '/path/to/rails/app/views/books/edit'
render '/path/to/rails/app/views/books/edit.html.erb'
render :file => '/path/to/rails/app/views/books/edit'
render :file => '/path/to/rails/app/views/books/edit.html.erb'
2.2.8 Rendering Text
render :text => "OK"
2.2.11 Rendering Vanilla JavaScript
Rails can render vanilla JavaScript (as an alternative to using update with an .rjs file):
render :js => "alert('Hello Rails');"
This will send the supplied string to the browser with a MIME type of text/javascript. 有点意思,可以直接调用 js的应用代码或者函数。
2.2.12 Options for rende
Calls to the render method generally accept four options:
- :content_type
- :layout
- :status
- :location
2.2.12.1 The :content_type Option
By default, Rails will serve the results of a rendering operation with the MIME content-type oftext/html (or application/json if you use the :json option, or application/xml for the :xmloption.).
2.2.12.2 The :layout Option
With most of the options to render, the rendered content is displayed as part of the current layout.
2.2.12.3 The :status Option
2.2.12.4 The :location Option
2.2.13 Finding Layouts
布局应用的优先级:
(1)Rails first looks for a file in app/views/layouts with the same base name as the controller。 首先寻找与控制器同名的布局
(2)然后If there is no such controller-specific layout, Rails will use app/views/layouts/application.html.erb orapp/views/layouts/application.builder.
(3)If there is no .erb layout, Rails will use a .builderlayout if one exists.
(4)当然,用户指定的布局具有最高的优先级。Rails also provides several ways to more precisely assign specific layouts to individual controllers and actions.
2.2.13.1 Specifying Layouts on a per-Controller Basis
2.2.13.2 Choosing Layouts at Runtime
这时layout所带的参数变得复杂,可以是method,也可以是Proc
2.2.13.3 Conditional Layouts
任何时候,任何事情都有例外,用于此正是如是。
2.2.13.4 Layout Inheritance
Layouts are shared downwards in the hierarchy, and more specific layouts always override more general ones
2.2.14 Avoiding Double Render Error
Rendor 陷阱,
The solution is simple: make sure that you only have one call to render orredirect in a single code path. One thing that can help is and return.
Make sure you use and return and not && return because while the former will work, the latter will not due to operator precedence in the Ruby Language.
另外:同一个方法中涉及两种可能layout的情形:
def show
@book = Book.find(params[:id])
if @book.special?
render :action => "special_show"
end
end
layout 谈论了不少,那么 <%=
render
'form'
%> 怎么回事呢? 似乎上文render也没有涉及到partial view的问题哦!
The <%= render 'form' %> line is our first introduction to partials in Rails. A partial is a snippet ofHTML and Ruby code that can be reused in multiple locations. In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.
具体参考
2.3 Using redirect_to
Another way to handle returning responses to an HTTP request is with redirect_to. As you’ve seen, render tells Rails which view (or other asset) to use in constructing a response. Theredirect_to method does something completely different: it tells the browser to send a new request for a different URL. For example, you could redirect from wherever you are in your code to the index of photos in your application with this call:
You can use redirect_to with any arguments that you could use with link_to or url_for.
2.3.2 The Difference Between render and redirect_to
非常重要的一点,
Your code stops running and waits for a new request for the browser. It just happens that you’ve told the browser what request it should make next, by sending back an HTTP 302 status code.
Remember, a render :action doesn’t run any code in the target action, so nothing will set up the variable that the target view is presumably depending on.
While in a small app, this added latency might not be a problem, it is something to think about when speed of response is of the essence. redirect_to涉及两次request,对速度有所影响。
3.1 Asset Tags
When Rails renders a view as a response, it does so by combining the view with the current layout (using the rules for finding the current layout that were covered earlier in this guide). Within a layout, you have access to three tools for combining different bits of output to form the overall response:
- Asset tags
- yield and content_for
- Partials (初学者容易弄混的,Partials本身其实还是pure view而不是layout
3.2 Understanding yield
3.3 Using content_for
content_for实际的使用场合,这绝对是经验。
The content_for method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their own blocks of content inserted. It’s also useful for inserting tags that load page-specific javascript or css files into the header of an otherwise generic layout.
3.4 Using Partials
3.4.2 Using Partials to Simplify Views
通过partial view来实现重复利用,very good;
经验:For content that is shared among all pages in your application, you can use partials directly from layouts.
3.4.3 Partial Layouts
A partial can use its own layout file, just as a view can use a layout.
3.4.4 Passing Local Variables
Every partial also has a local variable with the same name as the partial (minus the underscore). 好好理解!
3.4.5 Rendering Collections
对collection中的每个值都进行(循环)的渲染,本质上是个循环,有点类似each。
Partials are very useful in rendering collections. When you pass a collection to a partial via the:collection option, the partial will be inserted once for each member in the collection:
<h1>Products</h1>
<%= render @products %>
涉及到集合渲染时,必须想到这里。
3.4.6 Local Variables
3.5 Using Nested Layouts