Tx 61f351822ee529d60702313757449dabb87670b6@22902333

Included in block 22,902,333 at 2018-05-31 04:23:30 (UTC)


Raw transaction

ref_block_num30,249
ref_block_prefix651,795,726
expiration2018-05-31 04:33:24
operations
0.
0.comment
1.
parent_author""
parent_permlinkcn
authorlinjiahung
permlinkrails-rails-render-1
title[Rails]Rails中render常見的用法(1)
body"![](https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Ruby_On_Rails_Logo.svg/1280px-Ruby_On_Rails_Logo.svg.png)
這篇筆記會聚焦render在controller中的常見用法。
## 預設render同名的view
在Rails中contoller中會預設去render與路由同名的view。舉例來說,當你在PagesController的index action中,即便你不指定render的view,Rails也會自動幫你找尋模板
```ruby=
class PagesController < ApplicationController
def index
@pages = Page.all
# render :new
# 即使沒有render,Rails也會自動幫你抓取app/views/pages/index.html.erb的模板
end
end
```
## render同一個controller下的template
以下的程式碼代表的是,當update不成功時,render同一個controller下的edit template
```ruby=
class PagesController < ApplicationController
def update
@page = Page.find(params[:id])
if @page.update(page_params)
redirect_to page_path(@page)
else
render :edit
# 用途跟render temlate: :edit一樣
end
end
end
```
## render其他contoller的view
如果想要
像是categories controller下的index template的話,可以這樣做
```ruby=
class PagesController < ApplicationController
def index
@pages = Page.all
render "categories/index"
# 路徑會是相對於app/view
end
end
```
## render使用inline選項
我們可以使用inline的選項,讓我們不使用view的模板,而是使用提供的一段erb程式碼
```ruby=
# app/controllers/pages_controller.rb
def index
pages = Page.all
render inline: "<% pages.each do |p| %><p><%= p.user %></p><% end %>"
end
```
頁面產生,
![](https://i.imgur.com/ryW8qOP.png)
雖然透過inline選項,可以將erb程式碼放在controller中render,但是實務上很少這麼做。
因為這種做法等於是在controller中混用了view,跟Rails的MVC原則相衝突,基本上還是會把要render的內容拉到模板中。
## render純文字(plain)
如果只想要render純文字,可以透過plain選項
```ruby=
# app/controllers/pages_controller.rb
def index
pages = Page.all
render plain: "安安,我是純文字"
end
```
可以得到
![](https://i.imgur.com/kXDgcp8.png)
當我們使用plain時,連預設的版型(layout)都不會使用。如果需要使用layout的話,記得加上`layout: true`
```ruby=
# app/controllers/pages_controller.rb
def index
pages = Page.all
render plain: "安安,我是純文字", layout: true
end
```
## render json
如果要render json的話,可以使用json option,並將想要傳遞的object透過實體變數傳入。
```ruby=
# app/controllers/pages_controller.rb
def index
@pages = Page.all
render json: @pages
end
```
這樣會得到
![](https://i.imgur.com/I2UHiMi.png)
這邊值得注意的是不需要對要render的object呼叫 to_json。因為:json選項會試射自動對object呼叫 to_json方法。
## render和redirect_to的不同
render告訴Rails要用那個View或是其他 Asset)。而redirect_to則是告訴瀏覽器對不同的URL發一個新請求。舉例來說,可以在程式碼任何一個地方做轉址,比如轉到 photos的index就會是
```ruby=
redirect_to photos_path
```
不過需要注意的是
> 一個action中只能有一個render或redirect_to,不然你會得到一個DoubleRenderError例外錯誤。
## 避免render多次
在上一段我們有提到,一個action中只能有一個redirect_to或render。如果你在同一個controller中render多次的話,
```ruby=
def show
@book = Book.find(params[:id])
if @book.special?
render action: "special_show"
end
render action: "regular_show"
end
```
你可能會得到以下的錯誤訊息
![](https://i.imgur.com/Vu7FYtu.png)
上面那段程式碼會出錯的原因是,當@book.special?為true時,會先render `special_show`接著再去render `regular_show`。當一個controller render多次時就會出現錯誤。
解決方法就是讓action只出現一次render或action。如果真的要使用多次,那要加上`and return`來離開目前的action。
### 使用`and return`
#### 多個render
```ruby=
def show
@book = Book.find(params[:id])
if @book.special?
render action: "special_show" and return
end
render action: "regular_show"
end
```
#### redirect_to和render同時存在
```ruby=
def show
@book = Book.find(params[:id])
if @book.special?
redirect_to root_path
end
render action: "regular_show"
end
```
## 各種同樣效果的render寫法
以下幾種寫法均能render app/views/books/edit.html.erb這個template。
> 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"
## 參考資料
[Rails 算繪與版型](https://rails.ruby.tw/layouts_and_rendering.html#%E4%BD%BF%E7%94%A8-redirect-to)
[Layout, Render 與 View Helper](https://railsbook.tw/chapters/15-layout-render-and-view-helper.html)
### Rails學習推薦書籍
- [為你自己學Ruby on Rails](http://www.books.com.tw/exep/assp.php/pk60905/products/0010765725?utm_source=pk60905&utm_medium=ap-books&utm_content=recommend&utm_campaign=ap-201805)([網頁版](https://railsbook.tw/))
- [Ruby on Rails 自習手冊:邁向鐵道工人之路](http://www.books.com.tw/exep/assp.php/pk60905/products/0010666097?loc=P_asv_003&utm_source=pk60905&utm_medium=ap-books&utm_content=recommend&utm_campaign=ap-201805)"
json_metadata{"tags":["cn","cn-reader","blog","ruby","rails"],"users":["book.special"],"image":["https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Ruby_On_Rails_Logo.svg/1280px-Ruby_On_Rails_Logo.svg.png","https://i.imgur.com/ryW8qOP.png","https://i.imgur.com/kXDgcp8.png","https://i.imgur.com/I2UHiMi.png","https://i.imgur.com/Vu7FYtu.png"],"links":["https://rails.ruby.tw/layouts_and_rendering.html#%E4%BD%BF%E7%94%A8-redirect-to","https://railsbook.tw/chapters/15-layout-render-and-view-helper.html","http://www.books.com.tw/exep/assp.php/pk60905/products/0010765725?utm_source=pk60905&utm_medium=ap-books&utm_content=recommend&utm_campaign=ap-201805","https://railsbook.tw/","http://www.books.com.tw/exep/assp.php/pk60905/products/0010666097?loc=P_asv_003&utm_source=pk60905&utm_medium=ap-books&utm_content=recommend&utm_campaign=ap-201805"],"app":"steemit/0.1","format":"markdown"}
extensions[]
signatures
0.2018b9f86579a2e97a5fa2111e0a153c809727ba8dfe988b8743da43123e40711b00ea931982c6471ef694361285439d69bb0633053444c4d24d79271bdb1dce4f
transaction_id61f351822ee529d60702313757449dabb87670b6
block_num22,902,333
transaction_num0