rails 雜記 - render and layout

官方文檔:http://guides.rubyonrails.org/layouts_and_rendering.htmljavascript

 

渲染 view

渲染 html.rb 與相應的 action controllerhtml

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

  

或者渲染 acitonjava

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

  

渲染另外一個不一樣的 controller數據庫

render "products/show"

  

或者更明確地寫做json

render template: "products/show"

  

渲染一個特別的文件瀏覽器

render file: "/u/apps/warehouse_app/current/app/views/products/show"

  

 

實際上,上面的都是實現同一個功能ruby

render :edit
render action: :edit
render "edit"
render "edit.html.erb"
render action: "edit"
render action: "edit.html.erb"
render "books/edit"
render "books/edit.html.erb"
render template: "books/edit"
render template: "books/edit.html.erb"
render "/path/to/rails/app/views/books/edit"
render "/path/to/rails/app/views/books/edit.html.erb"
render file: "/path/to/rails/app/views/books/edit"
render file: "/path/to/rails/app/views/books/edit.html.erb"

  

 

無 view 渲染

inline 默認應用 ERB 進行渲染併發

render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>"

  

除了ERB以外,還能夠指定 typeapp

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

  

渲染 plain text。默認不使用 layoutdom

render plain: "OK"

  

渲染 html。不加 html_safe 默認轉義

render html: "<strong>Not Found</strong>".html_safe

  

渲染 json 與 xml

render json: @product

render xml: @product

  

渲染 Vanilla js

render js: "alert('Hello Rails');"

  

渲染 raw body

render body: "raw"

 

設置具體選項

選項

:content_type
:layout
:location
:status
:formats

 

指定 content_type

默認 content_type 爲 text/html (or application/json if you use the :json option, or application/xml for the :xml option.)

render file: filename, content_type: "application/rss"

 

指定 layout

render layout: "special_layout"
 

禁用 layout

render layout: false

 

設置 location

render xml: photo, location: photo_url(photo)

 

設置 status

rails 會自動設置 狀態碼,手動設置

render status: 500
render status: :forbidden
 

指定格式化類型

render formats: :xml
render formats: [:json, :xml]
 
Controller 指定 layout
class ProductsController < ApplicationController
  layout "inventory"
  #...
end

 

還能夠限制 only 或 except。使用 only: 與 except:

class ProductsController < ApplicationController
  layout "product", except: [:index, :rss]
end
 
模板嵌套

controller 嵌套

# in app/controllers/application_controller
class ApplicationController < ActionController::Base
end
 
# in app/controllers/admin_controller
class AdminController < ApplicationController
end
 
# in app/controllers/admin/products_controller
class Admin::ProductsController < AdminController
  def index
  end
end
 

admin/products#index action 的路由的查詢順序爲

app/views/admin/products/
app/views/admin/
app/views/application/

 

避免渲染屢次

def show
  @book = Book.find(params[:id])
  if @book.special?
    render action: "special_show"
  end
end
 
路由重定向
redirect_to photos_url
 

或者

redirect_back(fallback_location: root_path)
 

這個的路由的 location 以 HTTP_REFERER header  爲準,若是沒有設置這個 header,就會使用fallback的 location

 

這裏調用 redirect_to時, Rails 默認使用 HTTP status code 302,做臨時重定向 temporary redirect(網頁不刷新,地址改變,這裏使用的js Turbolinks替換,強迫地址改變)。能夠手動指定 301 作永久重定向  permanent redirect (網頁刷新,地址改變)

redirect_to photos_path, status: 301
 

對於

get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" }

 

此處默認使用 301

 

render 與 redirect_to 區別

render action 不執行 action的代碼。而 redirect_to 執行 action的代碼。

好比:

此時使用 render直接返回到 index.html.erb 不執行 index action的代碼,報錯。

def index
  @books = Book.all
end
 
def show
  @book = Book.find_by(id: params[:id])
  if @book.nil?
    render action: "index"
  end
end
 

redirect_to 會返回一個 302 響應,瀏覽器接受響應併發起另外一個請求 /books,執行 index acction的代碼(查詢數據庫),很是耗時。

def index
  @books = Book.all
end
 
def show
  @book = Book.find_by(id: params[:id])
  if @book.nil?
    redirect_to action: :index
  end
end
 

爲避免二次請求,仍是使用 render,並從新獲取 @books:

def index
  @books = Book.all
end
 
def show
  @book = Book.find_by(id: params[:id])
  if @book.nil?
    @books = Book.all
    flash.now[:alert] = "Your book was not found"
    render "index"
  end
end

 

當 檢測到 @book爲空時,會從新計算 all the books,並 直接渲染  index.html.erb

此外,瀏覽器發出 flash的 alert信息告訴用法發生了什麼。

 

 

結構化 Layout
Asset tags
yield and content_for
Partials

 

Asset Tag Helpers
auto_discovery_link_tag
javascript_include_tag
stylesheet_link_tag
image_tag
video_tag
audio_tag

 

yield and content_for

在 layout中定義 yield 與 yield :head

<html>
  <head>
  <%= yield :head %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>
 

在頁面中使用

<% content_for :head do %>
  <title>A simple page</title>
<% end %>
 
<p>Hello, Rails!</p>
 

則 html 的渲染結果爲

<html>
  <head>
  <title>A simple page</title>
  </head>
  <body>
  <p>Hello, Rails!</p>
  </body>
</html>

 

Partials

直接 渲染,上面的 render 一個 partial  named _menu.html.erb

<%= render "menu" %>

 

設定 layout

這將使用 _graybar.html.erb 去渲染  _link_area.html.erb 這個 partial。

注意這裏的 layout 不是 layouts 目錄下的文件,而是與 partial 同目錄下的文件。

<%= render partial: "link_area", layout: "graybar" %>

 

定義 locals (傳遞局部變量)

new.html.erb

<h1>New zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
 

_form.html.erb

<%= form_for(zone) do |f| %>
  <p>
    <b>Zone name</b><br>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

 

渲染 Model

渲染到 customer 而且 object爲 parent 裏的 @new_customer

<%= render partial: "customer", object: @new_customer %>

直接渲染  _customer.html.erb ,objeect 爲 parent裏的 @customer

<%= render @customer %>
 
渲染 collection

index.html.erb

<h1>Products</h1>
<%= render partial: "product", collection: @products %>

 

_product.html.erb

<p>Product Name: <%= product.name %></p>
 

此外,index.html.erb 也能夠簡寫:

<h1>Products</h1>
<%= render @products %>

  

直接渲染向量

index.html.erb

<h1>Contacts</h1>
<%= render [customer1, employee1, customer2, employee2] %>
 

customers/_customer.html.erb

<p>Customer: <%= customer.name %></p>
 

employees/_employee.html.erb

<p>Employee: <%= employee.name %></p>
 

爲空處理

<h1>Products</h1>
<%= render(@products) || "There are no products available." %>
 

別名處理

<%= render partial: "product", collection: @products, as: :item %>
 

使用 根 Layout

app/views/layouts/application.html.erb

<html>
<head>
  <title><%= @page_title or "Page Title" %></title>
  <%= stylesheet_link_tag "layout" %>
  <style><%= yield :stylesheets %></style>
</head>
<body>
  <div id="top_menu">Top menu items here</div>
  <div id="menu">Menu items here</div>
  <div id="content"><%= content_for?(:content) ? yield(:content) : yield %></div>
</body>
</html>

  

app/views/layouts/news.html.erb

<% content_for :stylesheets do %>
  #top_menu {display: none}
  #right_menu {float: right; background-color: yellow; color: black}
<% end %>
<% content_for :content do %>
  <div id="right_menu">Right menu items here</div>
  <%= content_for?(:news_content) ? yield(:news_content) : yield %>
<% end %>
<%= render template: "layouts/application" %>
 

隱藏了頂部 menu,並增長了一個右部菜單。

這裏 content_for?(:news_content) 維護了另外一個 layout,若是不使用另外一個子模板,能夠僅僅使用 yield 替代。

相關文章
相關標籤/搜索