iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
1
自我挑戰組

毫無基礎學習 Ruby on Rails 的 甘苦心得系列 第 28

DAY 28 使用 render/jbuilder 輸出 JSON 格式

在開發手機應用程式或是一些前端比較吃重的網站應用程式時,常會需要跟後端伺服器交換資料,交換資料的格式常見的有 JSON 或 XML 等格式,這樣的交換介面又稱之 API(Application Programming Interface)。

輸出成 JSON 格式 - 使用 render

class UsersController < ApplicationController
    # ...[略]...

    def index
      @users = User.all
    end

    # ...[略]...
  end

原本畫面是這樣

https://ithelp.ithome.com.tw/upload/images/20191012/20118842zlqjXFfAtU.png

這邊的 index Action 如果沒特別聲明 render 方法,它就會去 app/views/users/ 目錄下找同名的 index.html.erb 來呈現畫面,如果不需要輸出 HTML 畫面,可以把 index Action 改成這樣:

def index
    @users = User.all
    render json: @users
end

輸出格式變JSON後

https://ithelp.ithome.com.tw/upload/images/20191012/20118842GGAMjZEv9J.png

使用 postman 整理 會變成

https://ithelp.ithome.com.tw/upload/images/20191012/20118842XhmruPTNIl.png

但這樣的寫法,原本 /users 的頁面連不上了,也就是說如果要同時可以呈現 HTML 跟 JSON,得另外想辦法:

輸出成 JSON 格式 - 使用 Jbuilder

當你使用 Scaffold 產生檔案的時候,在 View 的目錄裡有多一些特別的檔案:

這幾個結尾是 .json.jbuilder 的檔案,就跟 .html.erb 的概念一樣,.html.erb 是指會使用 ERB 樣版引擎來解讀這個檔案,並轉換成 HTML 格式;而 .json.jbuilder 則是使用 Jbuilder 這個 gem,把結果輸出成 JSON 格式。

讓我們看一下 app/views/candidates/index.json.jbuilder 這個檔案的內容:

json.array! @candidates, partial: 'candidates/candidate', as: :candidate

看來是去 render candidates/_candidate 這個檔案,裡面的內容是:

json.extract! candidate, :id, :name, :age, :party, :politics, :votes, :created_at, :updated_at
json.url candidate_url(candidate, format: :json)

意思大概就是會輸出 candidate 物件的 id、name…updated_at 等欄位的資料。

原本網址 http://localhost:3000/candidates 可以看到使用者列表,如果把網址後面加上 .json 變成 http://localhost:3000/candidates.json 就能得到跟前面 render json: @candidates 一樣的結果。

不只如此,/candidates/2 會用 HTML 格式輸出 2 號使用者資料,如果是 /candidates/2.json 則是會以 JSON 格式輸出這筆資料。

另外,如果我只想印出姓名跟 黨籍,可以把 candidates/_candidate.json.jbuilder 的內容修改成這樣:

json.extract! candidate, :name, :party
[
    {

        "name": "巧穎",
        "party": "無黨籍",
        
    },
    {
 
        "name": "阿定",
        "party": "時代力量",
 
    },
    {
    
        "name": "繆梅英",
        "party": "共產黨",
   
    },
    {
   
        "name": "蔡英文",
        "party": "無黨籍",
    
    }
]

使用 render json: @candidates 的寫法只能把 @candidates 的內容全部印出來,而使用 Jbuilder 則是可以微調要輸出的欄位。另一個好處就是原本 /candidates 的頁面還是可保持 HTML 的頁面呈現,只有 /users.json 的時候才會以 JSON 格式輸出。

為什麼加 .json 就可以了?
其實這算是 Route 做的好事,先看一下 rails routes 的結果

https://ithelp.ithome.com.tw/upload/images/20191012/20118842tY2IwmwJA5.png

後面那個 (.:format) 。假設你輸入網址 /users.html,後面的附檔名就會被捕捉成 format,如果在 Controller 的 Action 沒有特別聲明要以什麼方式 render,就會依據這個 format 去找對應的檔案,也就是說會找到 app/views/index.html.erb。

同理可證,當網址是輸入 /users.json,它會去找 app/views/index.json.jbuilder 來輸出結果。 而 format 的預設值是 html,所以如果後面沒有附檔名,像是 /users,則會去找 html 的樣版。

參考資料:

為你自己學Ruby on Rails


上一篇
DAY 27 PORO
下一篇
DAY 29 程式碼時光機 Git版控
系列文
毫無基礎學習 Ruby on Rails 的 甘苦心得30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2020-01-19 09:13:55

黨派XD

我要留言

立即登入留言