Layouts and Rendering in Rails
Sending Responses
render
The Controller returns the corresponding view automatically if it is named right. Alternatively you can use render to render a different view.
def update
@book = Book.find(params[:id])
if @book.update(book_params)
redirect_to(@book)
else
render :edit, status: :unprocessable_entity
end
end
If the view belongs to a different controller you need to specify it:
render "products/show"
You can also render not-views:
render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>"
render plain: "OK"
render html: helpers.tag.strong("Not Found")
render json: @product
render xml: @product
render js: "alert('Hello Rails');"
render body: "raw"
render file: "#{Rails.root}/public/404.html", layout: false
Options for render
# content type
render template: "feed", content_type: "application/rss"
# different layout
render layout: "special_layout"
render layout: false
# location (redirect)
render xml: photo, location: photo_url(photo)
# set status
render status: 500
render status: :forbidden
# specify format
render formats: :xml
render formats: [:json, :xml]
# Render a specific variant
render variants: [:mobile, :desktop]
# app/views/home/index.html+mobile.erb
# app/views/home/index.html+desktop.erb
Using Layouts
Rails automatically checks if there is a layout with the same name as the controller. Else it falls back to the application.html.erb. You can also set it manually.
class ProductsController < ApplicationController
layout "inventory"
#...
end
redirect_to
If you want the browser to make a completely new request, you can use redirect_to
redirect_to photos_url
# there's also redirect back
redirect_back(fallback_location: root_path)
# some browsers need the fallback location
Header-Only Responses
head :bad_request
# or use some options:
head :created, location: photo_path(@photo)