概要
ActiveRecordを継承したモデルへの値の格納の仕方や、値を入力した際にどのバリデーションに反応したのか調べた
前提条件
Rails: 5.2
Ruby: 2.6.1
本題
サンプルのユーザテーブルの定義
create_table :users do |t|
t.string :name
t.integer :state
t.timestamps
end
ユーザモデルの定義
nameの空文字チェックのバリエーションがある
class User < ApplicationRecord
validates :name, presence: true
enum state: { show: 0, hide: 1 }
end
モデルを一つ取得し、これをもとに説明する
> u = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 2, name: "テスト1", created_at: "2019-01-29 03:56:08", updated_at: "2019-03-11 02:52:09", state: "hide">
stateを単純に出力すると、DBに格納されている数値ではなく、enumで定義した文字列が表示される
> u.state
=> "hide"
代入方法
enumで定義したシンボルでも、文字列でも、DBに実際に格納される数値でも代入できる
シンボルの場合
u.state = :hide
=> :hide
irb(main):038:0> u.state
=> "hide"
文字列の場合
u.state = "show"
=> "show"
irb(main):046:0> u.state
=> "show"
数値の場合
> u.state = 0
=> 0
> u.state
=> "show"
定義外の値を代入すると
enumで定義した範囲外の数値を代入しようとするとエラーになる
> u.state = "show2"
ArgumentError ('show2' is not a valid state)
irb(main):047:0> u.state = "show2"
Traceback (most recent call last):
1: from (irb):47
ArgumentError ('show2' is not a valid state)
> u.state = :show2
ArgumentError ('show2' is not a valid state)
> u.state = 2
ArgumentError ('2' is not a valid state)
格納されている実際の値を参照する
デバッグやテストのときなどu.state
とすると実際にどの値が格納されているか確認したい場合は
read_attribute_before_type_cast
や属性名_before_type_cast
を使う
> u.state
=> "hide"
u.read_attribute_before_type_cast(:state)
=> 1
irb(main):070:0> u.state_before_type_cast
=> 1