Ruby on Rails:善用enum及human_attribute_name方法印出易讀的下拉選單內容

本篇文章包含四個部分:ActiveRecord::Enum說明及使用、human_attribute_name說明及使用、製作易讀的下拉選單、創建model共用模組印出選單選項,以下為詳細內容。

ActiveRecord::Enum說明及使用

直接在rails console任意撈取一筆訂單資料看看,查詢status,結果會像下面這樣

查詢status後,直接看到數字,根本無法直接得知各個數字代表的意思,到底3是代表付錢了還是作業中呢,實在無法從數字的結果得知,想要讓屬性更好辨識,這時候可以使用Rails的ActiveRecord內建的enum模組,根據ActiveRecord::Enum的官方文件,只要在model定義好特定欄位各種數字狀態所代表的意思,之後查詢資料時,就可以直接看到對應的意思,而不是數字了,例如在訂單Order這個model,先定義好狀態status的enum,像下面這樣

在rails 的console隨意撈取一筆資料

可以看到,已經不是出現3了!而是直接顯示在Order model 我們定義status的enum中3代表的意思 — shipping。

enum也可以讓我們直接檢查資料是不是特定狀態,例如這邊Order model隨機抓取一筆資料,使用not_paid?就可以確認一筆訂單是不是未付款狀態

其他定義在status enum的狀態像是paid, shipping..等等,也可以直接使用paid? shipping?這樣的方法來確認訂單狀態。

如果想直接查看status底下到底有多少狀態,enum也提供了方法讓我們去呼叫,規則就是model class去呼叫已經定義enum欄位複數名稱,像status的話就是statuses,所以這邊查看Order的status有多少狀態,就會寫成下面這樣

回傳的結果是一個hash,內容是我們定義在model中的enum的內容,就可以看到這個欄位有多少狀態了。

human_attribute_name說明及使用

not_paid直接被轉為Not paid了,human_attribute_name預設會將字串的連接符號換成空白,然後將第一個字改成大寫,如果不想使用human_attribute_name預設的轉換格式,則可以將對應的格式定義在locale檔案中,例如not_paid想轉換為Not Paid,就可以像下面這樣定義在locale檔案

從rails console查看使用human_attribute_name的結果

可以看到,not_paid就不是human_attribute_name預設的格式,變成在locale定義的格式 Not Paid了。

製作易讀的下拉選單

直接使用Order.statuses把所有的status內容都印出來,網頁上就會看到像這樣的下拉選單

看起來已經不錯了,但是not_paid看起來就是有點突兀,這個時候再搭配human_attribute_name讓下拉選單內容更美觀,可以先用human_attribute_name將選單內容組出,程式碼像下面這樣

從rails console直接執行這段程式,組出來的資料像下面這樣

human_attribute_name轉換後的結果跟對應的enum status都放進一個array了,把這個結果放到下拉選單的選項看看,程式碼像下面這樣,controller先把下拉選項組出,然後view直接讀取

網頁上看到的下拉選單就會像下面這樣

呈現出來的格式已經是比較正式的格式了,而不是原始碼的感覺。

創建model共用模組印出選單選項

[[“Not paid”, “not_paid”], [“Paid”, “paid”], [“Shipping”, “shipping”], [“Deliverd”, “deliverd”], [“Returned”, “returned”], [“Refunded”, “refunded”]]

為了讓不同的model可以任意擴充使用這樣的模組,這邊運用了一點metaprogramming的技巧,寫了一個EnumValueConcern,程式碼像下面這樣

有需要的model就可以直接include EnumValueConcern,像Order model這樣

include之後,Order model就可以對status跟shipment_mode這兩個屬性使用enum_options_for_select這個方法了,直接從rails console看看結果

兩個屬性都可以組出我們預期的格式

再來試一個Product model

在rails console試試看使用enum_options_for_select

結果也是跟預期一樣,把category定義的enum跟human_attribute_name轉換的結果都印出來了,果然寫一個module EnumValueConcern讓model共用真的是相當方便啊!

參考資料:

human_attribute_name官方文件

使用-avtiverecordenum-建立易讀的狀態屬性

--

--

Programming Skill learner and Sharer | Ruby on Rails | Golang | Vue.js | Web Map API

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
icelandcheng

Programming Skill learner and Sharer | Ruby on Rails | Golang | Vue.js | Web Map API