Lỗi this page isnt working http error 409

This guide focuses on the interaction between Controller and View in the Model-View-Controller triangle. As you know, the Controller is responsible for orchestrating the whole process of handling a request in Rails, though it normally hands off any heavy code to the Model. But then, when it's time to send a response back to the user, the Controller hands things off to the View. It's that handoff that is the subject of this guide.

Show

    In broad strokes, this involves deciding what should be sent as the response and calling an appropriate method to create that response. If the response is a full-blown view, Rails also does some extra work to wrap the view in a layout and possibly to pull in partial views. You'll see all of those paths later in this guide.

    From the controller's point of view, there are three ways to create an HTTP response:

    • Call to create a full response to send back to the browser
    • Call to send an HTTP redirect status code to the browser
    • Call to create a response consisting solely of HTTP headers to send back to the browser

    You've heard that Rails promotes "convention over configuration". Default rendering is an excellent example of this. By default, controllers in Rails automatically render views with names that correspond to valid routes. For example, if you have this code in your

    Books are coming soon!

    03 class:

    class BooksController < ApplicationController
    end
    

    And the following in your routes file:

    And you have a view file

    Books are coming soon!

    04:

    Books are coming soon!

    Rails will automatically render

    Books are coming soon!

    04 when you navigate to

    Books are coming soon!

    06 and you will see "Books are coming soon!" on your screen.

    However, a coming soon screen is only minimally useful, so you will soon create your

    Books are coming soon!

    07 model and add the index action to

    Books are coming soon!

    03:

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    Note that we don't have explicit render at the end of the index action in accordance with "convention over configuration" principle. The rule is that if you do not explicitly render something at the end of a controller action, Rails will automatically look for the

    Books are coming soon!

    09 template in the controller's view path and render it. So in this case, Rails will render the

    Books are coming soon!

    04 file.

    If we want to display the properties of all the books in our view, we can do so with an ERB template like this:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    The actual rendering is done by nested classes of the module

    Books are coming soon!

    11. 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.

    In most cases, the controller's method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behavior of

    Books are coming soon!

    00. 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.

    If you want to see the exact results of a call to

    Books are coming soon!

    00 without needing to inspect it in a browser, you can call

    Books are coming soon!

    16. This method takes exactly the same options as

    Books are coming soon!

    00, but it returns a string instead of sending a response back to the browser.

    If you want to render the view that corresponds to a different template within the same controller, you can use

    Books are coming soon!

    00 with the name of the view:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    If the call to

    Books are coming soon!

    19 fails, calling the

    Books are coming soon!

    19 action in this controller will render the

    Books are coming soon!

    21 template belonging to the same controller.

    If you prefer, you can use a symbol instead of a string to specify the action to render:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    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

    Books are coming soon!

    00, which accepts the full path (relative to

    Books are coming soon!

    1. of the template to render. For example, if you're running code in an

    Books are coming soon!

    24 that lives in

    Books are coming soon!

    25, you can render the results of an action to a template in

    Books are coming soon!

    26 this way:

    Rails knows that this view belongs to a different controller because of the embedded slash character in the string. If you want to be explicit, you can use the

    Books are coming soon!

    27 option (which was required on Rails 2.2 and earlier):

    render template: "products/show"
    

    The above two ways of rendering (rendering the template of another action in the same controller, and rendering the template of another action in a different controller) are actually variants of the same operation.

    In fact, in the

    Books are coming soon!

    03 class, inside of the update action where we want to render the edit template if the book does not update successfully, all of the following render calls would all render the

    Books are coming soon!

    21 template in the

    Books are coming soon!

    30 directory:

    render :edit
    render action: :edit
    render "edit"
    render action: "edit"
    render "books/edit"
    render template: "books/edit"
    

    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.

    The

    Books are coming soon!

    00 method can do without a view completely, if you're willing to use the

    Books are coming soon!

    32 option to supply ERB as part of the method call. This is perfectly valid:

    render inline: "<% products.each do |p| %>

    <%= p.name %>

    <% end %>"

    There is seldom any good reason to use this option. Mixing ERB into your controllers defeats the MVC orientation of Rails and will make it harder for other developers to follow the logic of your project. Use a separate erb view instead.

    By default, inline rendering uses ERB. You can force it to use Builder instead with the

    Books are coming soon!

    35 option:

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    You can send plain text - with no markup at all - back to the browser by using the

    Books are coming soon!

    36 option to

    Books are coming soon!

    00:

    Rendering pure text is most useful when you're responding to Ajax or web service requests that are expecting something other than proper HTML.

    By default, if you use the

    Books are coming soon!

    36 option, the text is rendered without using the current layout. If you want Rails to put the text into the current layout, you need to add the

    Books are coming soon!

    39 option and use the

    Books are coming soon!

    40 extension for the layout file.

    You can send an HTML string back to the browser by using the

    Books are coming soon!

    41 option to

    Books are coming soon!

    00:

    Books are coming soon!

    0

    This is useful when you're rendering a small snippet of HTML code. However, you might want to consider moving it to a template file if the markup is complex.

    When using

    Books are coming soon!

    43 option, HTML entities will be escaped if the string is not composed with

    Books are coming soon!

    44-aware APIs.

    JSON is a JavaScript data format used by many Ajax libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser:

    You don't need to call

    Books are coming soon!

    45 on the object that you want to render. If you use the

    Books are coming soon!

    46 option,

    Books are coming soon!

    00 will automatically call

    Books are coming soon!

    45 for you.

    Rails also has built-in support for converting objects to XML and rendering that XML back to the caller:

    You don't need to call

    Books are coming soon!

    49 on the object that you want to render. If you use the

    Books are coming soon!

    50 option,

    Books are coming soon!

    00 will automatically call

    Books are coming soon!

    49 for you.

    Rails can render vanilla JavaScript:

    Books are coming soon!

    1

    This will send the supplied string to the browser with a MIME type of

    Books are coming soon!

    53.

    You can send a raw content back to the browser, without setting any content type, by using the

    Books are coming soon!

    54 option to

    Books are coming soon!

    00:

    This option should be used only if you don't care about the content type of the response. Using

    Books are coming soon!

    36 or

    Books are coming soon!

    41 might be more appropriate most of the time.

    Unless overridden, your response returned from this render option will be

    Books are coming soon!

    58, as that is the default content type of Action Dispatch response.

    Rails can render a raw file from an absolute path. This is useful for conditionally rendering static files like error pages.

    Books are coming soon!

    2

    This renders the raw file (it doesn't support ERB or other handlers). By default it is rendered within the current layout.

    Using the

    Books are coming soon!

    59 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.

    Books are coming soon!

    60 is often a faster and better option if a layout isn't required.

    Rails can render objects responding to

    Books are coming soon!

    61.

    This calls

    Books are coming soon!

    62 on the provided object with the current view context.

    You can also provide the object by using the

    Books are coming soon!

    63 option to

    Books are coming soon!

    00:

    Books are coming soon!

    3

    Calls to the method generally accept six options:

    • Books are coming soon!

      67
    • Books are coming soon!

      68
    • Books are coming soon!

      69
    • Books are coming soon!

      70
    • Books are coming soon!

      71
    • Books are coming soon!

      72

    By default, Rails will serve the results of a rendering operation with the MIME content-type of

    Books are coming soon!

    74 (or

    Books are coming soon!

    75 if you use the

    Books are coming soon!

    46 option, or

    Books are coming soon!

    77 for the

    Books are coming soon!

    50 option.). There are times when you might like to change this, and you can do so by setting the

    Books are coming soon!

    67 option:

    Books are coming soon!

    4

    With most of the options to

    Books are coming soon!

    00, the rendered content is displayed as part of the current layout. You'll learn more about layouts and how to use them later in this guide.

    You can use the

    Books are coming soon!

    68 option to tell Rails to use a specific file as the layout for the current action:

    Books are coming soon!

    5

    You can also tell Rails to render with no layout at all:

    You can use the

    Books are coming soon!

    69 option to set the HTTP

    Books are coming soon!

    85 header:

    Books are coming soon!

    6

    Rails will automatically generate a response with the correct HTTP status code (in most cases, this is

    Books are coming soon!

    87). You can use the

    Books are coming soon!

    70 option to change this:

    Books are coming soon!

    7

    Rails understands both numeric status codes and the corresponding symbols shown below.

    Response Class HTTP Status Code Symbol Informational 100 :continue 101 :switching_protocols 102 :processing Success 200 :ok 201 :created 202 :accepted 203 :non_authoritative_information 204 :no_content 205 :reset_content 206 :partial_content 207 :multi_status 208 :already_reported 226 :im_used Redirection 300 :multiple_choices 301 :moved_permanently 302 :found 303 :see_other 304 :not_modified 305 :use_proxy 307 :temporary_redirect 308 :permanent_redirect Client Error 400 :bad_request 401 :unauthorized 402 :payment_required 403 :forbidden 404 :not_found 405 :method_not_allowed 406 :not_acceptable 407 :proxy_authentication_required 408 :request_timeout 409 :conflict 410 :gone 411 :length_required 412 :precondition_failed 413 :payload_too_large 414 :uri_too_long 415 :unsupported_media_type 416 :range_not_satisfiable 417 :expectation_failed 421 :misdirected_request 422 :unprocessable_entity 423 :locked 424 :failed_dependency 426 :upgrade_required 428 :precondition_required 429 :too_many_requests 431 :request_header_fields_too_large 451 :unavailable_for_legal_reasons Server Error 500 :internal_server_error 501 :not_implemented 502 :bad_gateway 503 :service_unavailable 504 :gateway_timeout 505 :http_version_not_supported 506 :variant_also_negotiates 507 :insufficient_storage 508 :loop_detected 510 :not_extended 511 :network_authentication_required

    If you try to render content along with a non-content status code (100-199, 204, 205, or 304), it will be dropped from the response.

    Rails uses the format specified in the request (or

    Books are coming soon!

    41 by default). You can change this passing the

    Books are coming soon!

    71 option with a symbol or an array:

    Books are coming soon!

    8

    If a template with the specified format does not exist an

    Books are coming soon!

    92 error is raised.

    This tells Rails to look for template variations of the same format. You can specify a list of variants by passing the

    Books are coming soon!

    72 option with a symbol or an array.

    An example of use would be this.

    Books are coming soon!

    9

    With this set of variants Rails will look for the following set of templates and use the first that exists.

    • Books are coming soon!

      95
    • Books are coming soon!

      96
    • Books are coming soon!

      97

    If a template with the specified format does not exist an

    Books are coming soon!

    92 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.

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    0

    To find the current layout, Rails first looks for a file in

    Books are coming soon!

    99 with the same base name as the controller. For example, rendering actions from the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    00 class will use

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    01 (or

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    02). If there is no such controller-specific layout, Rails will use

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    03 or

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    04. If there is no

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    05 layout, Rails will use a

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    06 layout if one exists. Rails also provides several ways to more precisely assign specific layouts to individual controllers and actions.

    You can override the default layout conventions in your controllers by using the declaration. For example:

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    1

    With this declaration, all of the views rendered by the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    08 will use

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    09 as their layout.

    To assign a specific layout for the entire application, use a

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    07 declaration in your

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    11 class:

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    2

    With this declaration, all of the views in the entire application will use

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    12 for their layout.

    You can use a symbol to defer the choice of layout until a request is processed:

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    3

    Now, if the current user is a special user, they'll get a special layout when viewing a product.

    You can even use an inline method, such as a Proc, to determine the layout. For example, if you pass a Proc object, the block you give the Proc will be given the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    13 instance, so the layout can be determined based on the current request:

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    4

    Layouts specified at the controller level support the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    14 and

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    15 options. These options take either a method name, or an array of method names, corresponding to method names within the controller:

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    5

    With this declaration, the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    16 layout would be used for everything but the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    17 and

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    18 methods.

    Layout declarations cascade downward in the hierarchy, and more specific layout declarations always override more general ones. For example:

    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      19

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      6
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      20

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      7
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      21

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      8
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      22

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      9

    In this application:

    • In general, views will be rendered in the

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      23 layout
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      24 will use the

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      23 layout
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      26 will use the

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      27 layout
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      28 will use no layout at all
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      29 will use the

      class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      30 layout

    Similar to the Layout Inheritance logic, if a template or partial is not found in the conventional path, the controller will look for a template or partial to render in its inheritance chain. For example:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    0

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    1

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    2

    The lookup order for an

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    31 action will be:

    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      32
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      33
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      34

    This makes

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    34 a great place for your shared partials, which can then be rendered in your ERB as such:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    3

    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

    Books are coming soon!

    00 works.

    For example, here's some code that will trigger this error:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    4

    If

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    37 evaluates to

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    38, Rails will start the rendering process to dump the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    39 variable into the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    40 view. But this will not stop the rest of the code in the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    41 action from running, and when Rails hits the end of the action, it will start to render the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    42 view - and throw an error. The solution is simple: make sure that you have only one call to

    Books are coming soon!

    00 or

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    44 in a single code path. One thing that can help is

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    45. Here's a patched version of the method:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    5

    Note that the implicit render done by ActionController detects if

    Books are coming soon!

    00 has been called, so the following will work without errors:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    6

    This will render a book with

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    47 set with the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    40 template, while other books will render with the default

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    41 template.

    Another way to handle returning responses to an HTTP request is with . As you've seen,

    Books are coming soon!

    00 tells Rails which view (or other asset) to use in constructing a response. The

    Books are coming soon!

    01 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 to return the user to the page they just came from. This location is pulled from the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    55 header which is not guaranteed to be set by the browser, so you must provide the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    56 to use in this case.

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    7

    Books are coming soon!

    01 and

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    54 do not halt and return immediately from method execution, but simply set HTTP responses. Statements occurring after them in a method will be executed. You can halt by an explicit

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    45 or some other halting mechanism, if needed.

    Rails uses HTTP status code 302, a temporary redirect, when you call

    Books are coming soon!

    01. If you'd like to use a different status code, perhaps 301, a permanent redirect, you can use the

    Books are coming soon!

    70 option:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    8

    Just like the

    Books are coming soon!

    70 option for

    Books are coming soon!

    00,

    Books are coming soon!

    70 for

    Books are coming soon!

    01 accepts both numeric and symbolic header designations.

    Sometimes inexperienced developers think of

    Books are coming soon!

    01 as a sort of

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    69 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:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    9

    With the code in this form, there will likely be a problem if the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    39 variable is

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    71. Remember, a

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    72 doesn't run any code in the target action, so nothing will set up the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    73 variable that the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    18 view will probably require. One way to fix this is to redirect instead of rendering:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    0

    With this code, the browser will make a fresh request for the index page, the code in the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    18 method will run, and all will be well.

    The only downside to this code is that it requires a round trip to the browser: the browser requested the show action with

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    76 and the controller finds that there are no books, so the controller sends out a 302 redirect response to the browser telling it to go to

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    77, the browser complies and sends a new request back to the controller asking now for the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    18 action, the controller then gets all the books in the database and renders the index template, sending it back down to the browser which then shows it on your screen.

    While in a small application, this added latency might not be a problem, it is something to think about if response time is a concern. We can demonstrate one way to handle this with a contrived example:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    1

    This would detect that there are no books with the specified ID, populate the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    73 instance variable with all the books in the model, and then directly render the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    80 template, returning it to the browser with a flash alert message to tell the user what happened.

    The method can be used to send responses with only headers to the browser. The

    Books are coming soon!

    02 method accepts a number or symbol (see ) representing an HTTP status code. The options argument is interpreted as a hash of header names and values. For example, you can return only an error header:

    This would produce the following header:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    2

    Or you can use other HTTP headers to convey other information:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    3

    Which would produce:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    4

    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
    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      83 and
    • Partials

    Asset tag helpers provide methods for generating HTML that link views to feeds, JavaScript, stylesheets, images, videos, and audios. There are six asset tag helpers available in Rails:

    You can use these tags in layouts or other views, although the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    85,

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    86, and

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    87, are most commonly used in the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    94 section of a layout.

    The asset tag helpers do not verify the existence of the assets at the specified locations; they simply assume that you know what you're doing and generate the link.

    The helper builds HTML that most browsers and feed readers can use to detect the presence of RSS, Atom, or JSON feeds. It takes the type of the link (

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    97,

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    98, or

    Books are coming soon!

    46), a hash of options that are passed through to url_for, and a hash of options for the tag:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    5

    There are three tag options available for the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    85:

    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      01 specifies the

      Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      02 value in the link. The default value is "alternate".
    • Books are coming soon!

      35 specifies an explicit MIME type. Rails will generate an appropriate MIME type automatically.
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      04 specifies the title of the link. The default value is the uppercase

      Books are coming soon!

      35 value, for example, "ATOM" or "RSS".

    The helper returns an HTML

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    08 tag for each source provided.

    If you are using Rails with the Asset Pipeline enabled, this helper will generate a link to

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    09 rather than

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    10 which was used in earlier versions of Rails. This link is then served by the asset pipeline.

    A JavaScript file within a Rails application or Rails engine goes in one of three locations:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    11,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    12 or

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    13. These locations are explained in detail in the .

    You can specify a full path relative to the document root, or a URL, if you prefer. For example, to link to a JavaScript file that is inside a directory called

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    14 inside of one of

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    11,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    12 or

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    13, you would do this:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    6

    Rails will then output a

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    08 tag such as this:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    7

    The request to this asset is then served by the Sprockets gem.

    To include multiple files such as

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    19 and

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    20 at the same time:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    8

    To include

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    19 and

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    22:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    9

    To include

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    23:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    0

    The helper returns an HTML

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    26 tag for each source provided.

    If you are using Rails with the "Asset Pipeline" enabled, this helper will generate a link to

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    27. This link is then processed by the Sprockets gem. A stylesheet file can be stored in one of three locations:

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    11,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    12, or

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    13.

    You can specify a full path relative to the document root, or a URL. For example, to link to a stylesheet file that is inside a directory called

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    31 inside of one of

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    11,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    12, or

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    13, you would do this:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    1

    To include

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    35 and

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    36:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    2

    To include

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    35 and

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    38:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    3

    To include

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    39:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    4

    By default, the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    87 creates links with

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    41. You can override this default by specifying an appropriate option (

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    01):

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    5

    The helper builds an HTML

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    45 tag to the specified file. By default, files are loaded from

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    46.

    Note that you must specify the extension of the image.

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    6

    You can supply a path to the image if you like:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    7

    You can supply a hash of additional HTML options:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    8

    You can supply alternate text for the image which will be used if the user has images turned off in their browser. If you do not specify an alt text explicitly, it defaults to the file name of the file, capitalized and with no extension. For example, these two image tags would return the same code:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render :edit, status: :unprocessable_entity
      end
    end
    

    9

    You can also specify a special size tag, in the format "{width}x{height}":

    render template: "products/show"
    

    0

    In addition to the above special tags, you can supply a final hash of standard HTML options, such as

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    47,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    48, or

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    49:

    render template: "products/show"
    

    1

    The helper builds an HTML5

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    52 tag to the specified file. By default, files are loaded from

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    53.

    render template: "products/show"
    

    2

    Produces

    render template: "products/show"
    

    3

    Like an

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    88 you can supply a path, either absolute, or relative to the

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    53 directory. Additionally you can specify the

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    56 option just like an

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    88. Video tags can also have any of the HTML options specified at the end (

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    58,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    59 et al).

    The video tag also supports all of the

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    52 HTML options through the HTML options hash, including:

    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      61, provides an image to put in place of the video before it starts playing.
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      62, starts playing the video on page load.
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      63, loops the video once it gets to the end.
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      64, provides browser supplied controls for the user to interact with the video.
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      65, the video will pre load the file for the user on page load.

    You can also specify multiple videos to play by passing an array of videos to the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    89:

    render template: "products/show"
    

    4

    This will produce:

    render template: "products/show"
    

    5

    The helper builds an HTML5

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    69 tag to the specified file. By default, files are loaded from

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    70.

    render template: "products/show"
    

    6

    You can supply a path to the audio file if you like:

    render template: "products/show"
    

    7

    You can also supply a hash of additional options, such as

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    48,

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    47, etc.

    Like the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    89, the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    90 has special options:

    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      62, starts playing the audio on page load
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      64, provides browser supplied controls for the user to interact with the audio.
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      65, the audio will pre load the file for the user on page load.

    Within the context of a layout,

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83 identifies a section where content from the view should be inserted. The simplest way to use this is to have a single

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83, into which the entire contents of the view currently being rendered is inserted:

    render template: "products/show"
    

    8

    You can also create a layout with multiple yielding regions:

    render template: "products/show"
    

    9

    The main body of the view will always render into the unnamed

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83. To render content into a named

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83, you use the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    84 method.

    The method allows you to insert content into a named

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83 block in your layout. For example, this view would work with the layout that you just saw:

    render :edit
    render action: :edit
    render "edit"
    render action: "edit"
    render "books/edit"
    render template: "books/edit"
    

    0

    The result of rendering this page into the supplied layout would be this HTML:

    render :edit
    render action: :edit
    render "edit"
    render action: "edit"
    render "books/edit"
    render template: "books/edit"
    

    1

    The

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    84 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.

    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.

    To render a partial as part of a view, you use the method within the view:

    This will render a file named

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    89 at that point within the view being rendered. Note the leading underscore character: partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore. This holds true even when you're pulling in a partial from another folder:

    render :edit
    render action: :edit
    render "edit"
    render action: "edit"
    render "books/edit"
    render template: "books/edit"
    

    2

    Since view partials rely on the same as templates and layouts, that code will pull in the partial from

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    90.

    One way to use partials is to treat them as the equivalent of subroutines: as a way to move details out of a view so that you can grasp what's going on more easily. For example, you might have a view that looked like this:

    render :edit
    render action: :edit
    render "edit"
    render action: "edit"
    render "books/edit"
    render template: "books/edit"
    

    3

    Here, the

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    91 and

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    92 partials could contain content that is shared by many pages in your application. You don't need to see the details of these sections when you're concentrating on a particular page.

    As seen in the previous sections of this guide,

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83 is a very powerful tool for cleaning up your layouts. Keep in mind that it's pure Ruby, so you can use it almost everywhere. For example, we can use it to DRY up form layout definitions for several similar resources:

    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      94

      render :edit render action: :edit render "edit" render action: "edit" render "books/edit" render template: "books/edit"

      4
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      95

      render :edit render action: :edit render "edit" render action: "edit" render "books/edit" render template: "books/edit"

      5
    • Listing Books

      <% @books.each do |book| %>  
        
      <% end %>
      Title Content
      <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

      <%= link_to "New book", new_book_path %>

      96

      render :edit render action: :edit render "edit" render action: "edit" render "books/edit" render template: "books/edit"

      6

    For content that is shared among all pages in your application, you can use partials directly from layouts.

    A partial can use its own layout file, just as a view can use a layout. For example, you might call a partial like this:

    render :edit
    render action: :edit
    render "edit"
    render action: "edit"
    render "books/edit"
    render template: "books/edit"
    

    7

    This would look for a partial named

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    97 and render it using the layout

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    98. Note that layouts for partials follow the same leading-underscore naming as regular partials, and are placed in the same folder with the partial that they belong to (not in the master

    Listing Books

    <% @books.each do |book| %> <% end %>
    Title Content
    <%= book.title %> <%= book.content %> <%= link_to "Show", book %> <%= link_to "Edit", edit_book_path(book) %> <%= link_to "Destroy", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>

    <%= link_to "New book", new_book_path %>

    99 folder).

    Also note that explicitly specifying

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    00 is required when passing additional options such as

    Books are coming soon!

    68.

    You can also pass local variables into partials, making them even more powerful and flexible. For example, you can use this technique to reduce duplication between new and edit pages, while still keeping a bit of distinct content:

    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      02

      render :edit render action: :edit render "edit" render action: "edit" render "books/edit" render template: "books/edit"

      8
    • Books are coming soon!

      21

      render :edit render action: :edit render "edit" render action: "edit" render "books/edit" render template: "books/edit"

      9
    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      04

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      0

    Although the same partial will be rendered into both views, Action View's submit helper will return "Create Zone" for the new action and "Update Zone" for the edit action.

    To pass a local variable to a partial in only specific cases use the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    05.

    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      80

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      1
    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      07

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      2
    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      08

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      3

    This way it is possible to use the partial without the need to declare all local variables.

    Every partial also has a local variable with the same name as the partial (minus the leading underscore). You can pass an object in to this local variable via the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    09 option:

    render inline: "<% products.each do |p| %>

    <%= p.name %>

    <% end %>"

    4

    Within the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    10 partial, the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    10 variable will refer to

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    12 from the parent view.

    If you have an instance of a model to render into a partial, you can use a shorthand syntax:

    Assuming that the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    13 instance variable contains an instance of the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    14 model, this will use

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    15 to render it and will pass the local variable

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    10 into the partial which will refer to the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    13 instance variable in the parent view.

    Partials are very useful in rendering collections. When you pass a collection to a partial via the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    18 option, the partial will be inserted once for each member in the collection:

    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      80

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      5
    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      20

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      6

    When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    21, and within the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    21 partial, you can refer to

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    16 to get the instance that is being rendered.

    There is also a shorthand for this. Assuming

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    24 is a collection of

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    25 instances, you can simply write this in the

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    80 to produce the same result:

    render inline: "<% products.each do |p| %>

    <%= p.name %>

    <% end %>"

    7

    Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection:

    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      80

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      8
    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      28

      render inline: "<% products.each do |p| %>

      <%= p.name %>

      <% end %>"

      9
    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      29

      render inline: "xml.p {'Horrid coding practice!'}", type: :builder

      0

    In this case, Rails will use the customer or employee partials as appropriate for each member of the collection.

    In the event that the collection is empty,

    Books are coming soon!

    00 will return nil, so it should be fairly simple to provide alternative content.

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    1

    To use a custom local variable name within the partial, specify the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    31 option in the call to the partial:

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    2

    With this change, you can access an instance of the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    24 collection as the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    33 local variable within the partial.

    You can also pass in arbitrary local variables to any partial you are rendering with the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    34 option:

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    3

    In this case, the partial will have access to a local variable

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    35 with the value "Products Page".

    Rails also makes a counter variable available within a partial called by the collection. The variable is named after the title of the partial followed by

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    36. For example, when rendering a collection

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    24 the partial

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    20 can access the variable

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    39. The variable indexes the number of times the partial has been rendered within the enclosing view, starting with a value of

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    40 on the first render.

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    4

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    5

    This also works when the partial name is changed using the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    41 option. So if you did

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    42, the counter variable would be

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    43.

    You can also specify a second partial to be rendered between instances of the main partial by using the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    44 option:

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    6

    Rails will render the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    45 partial (with no data passed in to it) between each pair of

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    21 partials.

    When rendering collections it is also possible to use the

    Books are coming soon!

    68 option:

    render inline: "xml.p {'Horrid coding practice!'}", type: :builder
    

    7

    The layout will be rendered together with the partial for each item in the collection. The current object and object_counter variables will be available in the layout as well, the same way they are within the partial.

    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 following

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    11 layout:

    • class BooksController < ApplicationController def index

      @books = Book.all  
      
      end end

      03

      render inline: "xml.p {'Horrid coding practice!'}", type: :builder

      8

    On pages generated by

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    50, you want to hide the top menu and add a right menu:

    • def update @book = Book.find(params[:id]) if @book.update(book_params)

      redirect_to(@book)  
      
      else
      render "edit"  
      
      end end

      51

      render inline: "xml.p {'Horrid coding practice!'}", type: :builder

      9

    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

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    52 method via

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    53 to base a new layout on the News layout. If you are sure you will not subtemplate the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    54 layout, you can replace the

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
      end
    end
    

    55 with simply

    class BooksController < ApplicationController
      def index
        @books = Book.all
      end
    end
    

    83.

    Feedback

    You're encouraged to help improve the quality of this guide.

    Please contribute if you see any typos or factual errors. To get started, you can read our section.

    You may also find incomplete content or stuff that is not up to date. Please do add any missing documentation for main. Make sure to check Edge Guides first to verify if the issues are already fixed or not on the main branch. Check the Ruby on Rails Guides Guidelines for style and conventions.

    If for whatever reason you spot something to fix but cannot patch it yourself, please open an issue.

    And last but not least, any kind of discussion regarding Ruby on Rails documentation is very welcome on the official Ruby on Rails Forum.