1.Getting Started with Rails
1.1 数据在MVC之间共享传递的问题
1.2
2. Action Controller Overview
2.1 Parameters
There are two kinds of parameters possible in a web application. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the params hash in your controller.
2.2 Hash and Array Parameters
2.3 ? Routing Parameters
2.4 ?default_url_options
2.2 Session
3. Layouts and Rendering in Rails
3.1 Creating Responses
From the controller’s point of view, there are three ways to create an HTTP response:
Call render to create a full response to send back to the browserCall redirect_to to send an HTTP redirect status code to the browserCall head to create a response consisting solely of HTTP headers to send back to the browser3.1.1 Rendering by Default: Convention Over Configuration in 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, so in this case, Rails will render the app/views/books/index.html.erb file. 如果controller没有涉及任何关于render的说明,那么使用默认规则:action_name.html.erb
比如这种情况:
class BooksController < ApplicationController def index @books = Book.all end end 或者: def index @posts = Post.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } end end
3.1.2 Using render
In most cases, the ActionController::Base#render method does the heavy lifting of rendering your application’s content for use by a browser. There are a variety of ways to customise the behaviour of 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.
render_to_string method takes exactly the same options as render , but it returns a string instead of sending a response back to the browser.
(1)Rendering Nothing:render :nothing => true
(2)Rendering an Action’s View
render "edit" render :edit render :action => "edit" (:action option is no longer necessary in Rails 3.0) Using render with :action is a frequent source of confusion for Rails newcomers. 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 . 这句说得好,这里:action 的作用是为了指明对应那个view,而不是去执行controller中执行这个action方法的。
比如下面程序,:action 只是为了说明 that If the call to update_attributes fails, calling the update action in this controller will render the edit.html.erb template belonging to the same controller .
def update @book = Book.find(params[ :id ]) if @book .update_attributes(params[ :book ]) redirect_to( @book ) else render :action => "edit" end end end (3)Rendering an Action’s Template from Another Controller render 'products/show' or render :template => 'products/show' (Rails 2.2) (4)Rendering an Arbitrary File The render method can also use a view that’s entirely outside of your application (perhaps you’re sharing views between two Rails applications). The :file option takes an absolute file-system path. Of course, you need to have rights to the view that you’re using to render the content. render "/u/apps/warehouse_app/current/app/views/products/show" or render :file => "/u/apps/warehouse_app/current/app/views/products/show" (Rails2.2) 3.1.3 Finding Layouts To find the current layout, Rails first looks for a file in app/views/layouts with the same base name as the controller. For example, rendering actions from the PhotosController class will use app/views/layouts/photos.html.erb (or app/views/layouts/photos.builder ). If there is no such controller-specific layout, Rails will use app/views/layouts/application.html.erb or app/views/layouts/application.builder . If there is no .erb layout, Rails will use a .builder layout if one exists. (1) Specifying Layouts on a per-Controller Basis (2) To assign a specific layout for the entire application, use a declaration in your ApplicationController class (3) Choosing Layouts at Runtime (4) You can also decide the layout by passing a Proc object (5) Conditional Layouts, :only or :except (6) Layout Inheritance Layouts are shared downwards in the hierarchy, and more specific layouts always override more general ones. (7) Avoiding Double Render Errors Sooner or later, most Rails developers will see the error message “Can only render or redirect once per action”. While this is annoying, it’s relatively easy to fix. Usually it happens because of a fundamental misunderstanding of the way that render works. 3.2 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. The redirect_to method does something completely different: it tells the browser to send a new request for a different URL . (1) redirect_to photos_path (2) You can use redirect_to with any arguments that you could use with link_to or url_for . In addition, there’s a special redirect that sends the user back to the page they just came from: redirect_to :back (3) The Difference Between render and redirect_to Very good Example here: example1: def index @books = Book.all end def show @book = Book.find_by_id(params[ :id ]) if @book . nil ? render :action => "index" end end With the code in this form, there will be likely be a problem if the @book variable is nil . Remember, a render :action doesn’t run any code in the target action, so nothing will set up the @books variable that the index view is presumably depending on. One way to fix this is to redirect instead of rendering: example2: def index @books = Book.all end def show @book = Book.find_by_id(params[ :id ]) if @book . nil ? redirect_to :action => :index end end Another meaningful example: def index @books = Book.all end def show @book = Book.find_by_id(params[ :id ]) if @book . nil ? @books = Book.all render "index" , :alert => 'Your book was not found!' end end 说明了几个要点: P1, 不发送新的request,怎么样解决数据读取和传递的问题。 这是同一个controller, 从show 这个action 直接获取index的view,而且还得将数据从show“传递”过去(实际上没有传递的概念,controller的实例变量,view都可以访问); P2,是Flash的功能; P3, 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. 3.3 Using head To Build Header-Only Responses The head method can be used to send responses with only headers to the browser. It provides a more obvious alternative to calling render :nothing . The head method takes one parameter, which is interpreted as a hash of header names and values. 第一个参数对应到 HTTP header, 如 HTTP/1.1 400 Bad Request. 3.4 Structuring LayoutsWhen Rails renders a view as a response, it does so by combining the view with the current layout. Within a layout, you have access to three tools for combining different bits of output to form the overall response:
Asset tagsyield and content_for Partials 3.4.1 Asset tag auto_discovery_link_tag javascript_include_tag stylesheet_link_tag image_tag video_tag audio_tag 3.4.2 Understanding yield The main body of the view will always render into the unnamed yield . To render content into a named yield , you use the content_for method. 3.4.3 Using content_for 结合 3.4.2 一起看 The content_for method allows you to insert content into a named yield block in your layout. For example, this view would work with the layout that you just saw. 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.4 Partial templates – usually just called “partials” – are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file. 3.4.4.1 Naming Partials 3.4.4.2 Using Partials to Simplify Views 3.4.4.3 Partial Layouts A partial can use its own layout file, just as a view can use a layout. <%= render "link_area" , :layout => "graybar" %> 3.4.4.4 Passing Local Variables You can also pass local variables into partials, making them even more powerful and flexible. 3.4.4.5 Rendering Collections 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: <%= render :partial => "product" , :collection => @products %> In Rails 3.0, there is also a shorthand for this. Assuming @products is a collection of product instances. Rails determines the name of the partial to use by looking at the model name in the collection. 3.4.4.6 Local Variables 3.4.5 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). ??? Learn More.