「原則」就表示可以打破,這裡分享的是筆者自己本身參與rails的專案,當需要建立新的欄位時會遵守的一些原則,但不代表這些原則會滿足各種的使用情境,所以在設計欄位時還是要以實際的需求來做考量。
代表過期的時間欄位會命名為expired_at
,付款完成的時間欄位會命名為paid_at
。
在 migrate 中的金錢欄位可以寫成t.decimal :unit_price, precision: 15, scale: 5
。
如果 user 的 name 欄位是必填,則在 user 的 migration 中加上t.string :name, null: false
並在 User model 中加上validates :name, presence: true
如果 user 的 name 欄位是唯一,則在 user 的 migration 中加上add_index :users, :name, unique: true
,因為不加 validation,所以要記得做 exception handling。
例如售出數量(sale_count)一開始一定為0,則可以在 migration 中加上t.integer :sale_count, default: 0, null: false
,最大可購買數量(max_sale_per_order)有預設值是5,但未來有可能變動,則 migration 不加 default,但在 model 中可以使用 default_value_for 來設定:
class Ticket < ActiveRecord::Base
# ...
DEFAULT_MAX_SALE_PER_ORDER = 5
default_value_for :max_sale_per_order, DEFAULT_MAX_SALE_PER_ORDER
# ...
end
例如 order 有關聯到使用者,則在 order 的 migration 會加上t.references :course, foreign_key: true, null: false
。你也可以使用rails model generator,例如可以下rg model Order user:references (...)
,這時候 migration 預設會產生t.references :user, index: true, foreign_key: true
。但請記得要視情況去掉 indxe: true 或是加上 null: false 。
例如訂單的訂單編號(order_number)只會有20字元的長度,則在 order 的 migration 可加上t.string :order_number, :limit: 20, null: false
,在 order model 中則加上validates :order_number, length: { is: 20 }
。另外,文字欄位則可以依照長度需求視情況選擇使用 string 或是 text。在使用 integer 的 limit 時要特別注意,它不是指數字的位數,而是指數字欄位所使用的位元數(很容易踩到的坑),請參考rails migration中integer column的limit。
訂單記錄付款方式(payment_method)的欄位,每個訂單只會有一種付款方式,而且事先就知道有哪一些付款方式,也就是說付款方式是事先定義好的。則 payment_method 在 order 的 migration 會是t.integer :payment_method, :limit: 1, null: false
,而在 Order model 中會設定 payment_method enumerize 如下:
class Order < ActiveRecord::Base
# ...
PAYMENT_METHODS = {
credit_card: 0,
atm: 1,
paypal: 2,
alipay: 3,
cash: 4
}
extend Enumerize
enumerize :payment_method, in: PAYMENT_METHODS, scope: true
# ...
end
在實際使用 payment_method 的欄位時,都用對應的字串操作,但資料庫欄位儲存的是對應的數值。
order.payment_method # 'credit_card'
order.payment_method = 'atm'
order.credit_card? # false
Order.with_payment_method('paypal')
傳送門:enumerize
這裡與資料庫欄位比較沒有關係,但當 model 需要處理一些特定的問題,使用下面的 gem 會特別方便。
例如在 User model 中有一個欄位是存取代碼(access_token),它會在一個 user 被建立的時候自動產生,而且之後不能去修改這個欄位的值,則在 User model 中就可以使用 uidable 來設定這個欄位:
class User < ActiveRecord::Base
# ...
include Uidable
uidable uid_name: :access_token, scope: true
# ...
end
要注意的是,雖然這個欄位在資料建立的時候預設會使用 unique validation,但如果要讓這個欄位唯一,在 migration 中還是要記得加 unique index。
傳送門:uidable
傳送門:aasm
傳送門:acts_as_list