diff options
Diffstat (limited to 'guides/source/layouts_and_rendering.md')
-rw-r--r-- | guides/source/layouts_and_rendering.md | 89 |
1 files changed, 59 insertions, 30 deletions
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md index ad08e5a5a9..ce90a60e36 100644 --- a/guides/source/layouts_and_rendering.md +++ b/guides/source/layouts_and_rendering.md @@ -97,7 +97,7 @@ If we want to display the properties of all the books in our view, we can do so <%= link_to "New book", new_book_path %> ``` -NOTE: The actual rendering is done by nested classes of the module [`ActionView::Template::Handlers`](http://api.rubyonrails.org/classes/ActionView/Template/Handlers.html). This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. +NOTE: The actual rendering is done by nested classes of the module [`ActionView::Template::Handlers`](https://api.rubyonrails.org/classes/ActionView/Template/Handlers.html). This guide does not dig into that process, but it's important to know that the file extension on your view controls the choice of template handler. ### Using `render` @@ -149,25 +149,6 @@ Rails knows that this view belongs to a different controller because of the embe render template: "products/show" ``` -#### Rendering an Arbitrary File - -The `render` method can also use a view that's entirely outside of your application: - -```ruby -render file: "/u/apps/warehouse_app/current/app/views/products/show" -``` - -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. - -NOTE: Using the `:file` option in combination with users input can lead to security problems -since an attacker could use this action to access security sensitive files in your file system. - -NOTE: By default, the file is rendered using the current layout. - -TIP: If you're running Rails on Microsoft Windows, you should use the `:file` option to -render a file, because Windows filenames do not have the same format as Unix filenames. - #### Wrapping it up The above three ways of rendering (rendering another template within the controller, rendering a template within another controller, and rendering an arbitrary file on the file system) are actually variants of the same action. @@ -178,17 +159,9 @@ In fact, in the BooksController class, inside of the update action where we want 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" ``` Which one you use is really a matter of style and convention, but the rule of thumb is to use the simplest one that makes sense for the code you are writing. @@ -287,6 +260,23 @@ time. NOTE: Unless overridden, your response returned from this render option will be `text/plain`, as that is the default content type of Action Dispatch response. +#### Rendering raw file + +Rails can render a raw file from an absolute path. This is useful for +conditionally rendering static files like error pages. + +```ruby +render file: "#{Rails.root}/public/404.html", layout: false +``` + +This renders the raw file (it doesn't support ERB or other handlers). By +default it is rendered within the current layout. + +WARNING: Using the `:file` option in combination with users input can lead to security problems +since an attacker could use this action to access security sensitive files in your file system. + +TIP: `send_file` is often a faster and better option if a layout isn't required. + #### Options for `render` Calls to the `render` method generally accept five options: @@ -296,13 +286,14 @@ Calls to the `render` method generally accept five options: * `:location` * `:status` * `:formats` +* `:variants` ##### The `:content_type` Option By default, Rails will serve the results of a rendering operation with the MIME content-type of `text/html` (or `application/json` if you use the `:json` option, or `application/xml` for the `:xml` option.). There are times when you might like to change this, and you can do so by setting the `:content_type` option: ```ruby -render file: filename, content_type: "application/rss" +render template: "feed", content_type: "application/rss" ``` ##### The `:layout` Option @@ -417,6 +408,44 @@ render formats: [:json, :xml] If a template with the specified format does not exist an `ActionView::MissingTemplate` error is raised. +##### The `:variants` Option + +This tells Rails to look for template variations of the same format. +You can specify a list of variants by passing the `:variants` option with a symbol or an array. + +An example of use would be this. + +```ruby +# called in HomeController#index +render variants: [:mobile, :desktop] +``` + +With this set of variants Rails will look for the following set of templates and use the first that exists. + +- `app/views/home/index.html+mobile.erb` +- `app/views/home/index.html+desktop.erb` +- `app/views/home/index.html.erb` + +If a template with the specified format does not exist an `ActionView::MissingTemplate` error is raised. + +Instead of setting the variant on the render call you may also set it on the request object in your controller action. + +```ruby +def index + request.variant = determine_variant +end + +private + +def determine_variant + variant = nil + # some code to determine the variant(s) to use + variant = :mobile if session[:use_mobile] + + variant +end +``` + #### 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. Rails also provides several ways to more precisely assign specific layouts to individual controllers and actions. @@ -650,7 +679,7 @@ Just like the `:status` option for `render`, `:status` for `redirect_to` accepts #### The Difference Between `render` and `redirect_to` -Sometimes inexperienced developers think of `redirect_to` as a sort of `goto` command, moving execution from one place to another in your Rails code. This is _not_ correct. 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. +Sometimes inexperienced developers think of `redirect_to` as a sort of `goto` command, moving execution from one place to another in your Rails code. This is _not_ correct. Your code stops running and waits for a new request from 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. Consider these actions to see the difference: |