Help us understand the problem. What is going on with this article?

【Rails】Hash,Enumのハマりどころ個人まとめ

fetchメソッドのデフォルト値を設定する

sp.object.sample&.fetch("name", nil)

#(key, デフォルト値)で設定できる

【デフォルト値を設定しておくメリット】

  • nilの場合に対応できる。(RDBでJSON管理をしている場合、valueがnullだとViewに渡した際にKeyErrorが発生する)
  • KeyErrorが防げる
  • データの欠落を防げる

大体似通ったりだが、こんなところかな

お世話になった素晴らしい参考サイト

ハッシュデータのバリデーション

【Rails】カスタムバリデータ JSON

&.

Enum 0と1の場合

# RDBではTinyIntに相当するものに使用する
enum has_milk: { # ミルクの希望
  desired: 1, # 希望する
  not_desired: 0, # 希望しない
}, _suffix: true

取得は、nilになるようだ

カラム型TINYINTの場合にActiveRecord::Enumを使いたいより抜粋

stateカラムがTINYINTだった。ActiveRecordは、カラムがTINYINT(1)の場合、
自動的にbooleanとみなしてキャストするらしい。今回の場合(enumの場合)、
enumのvalueにしていたのが数値だったために「(キャストした値)true/falseに該当するlabelがない」=> nilとなっていた様子。

以上のケースと全く同じ挙動がみられる

sample = Reservation::Lunch.find(2)
sample.has_milk
=> nil
Reservation::Lunch.has_milks[:desired]
=> 1
sample.has_milk = Reservation::Lunch.has_milks[:desired]
=> 1
sample.has_milk
=> "desired"
Reservation::Lunch.has_milks[:not_desired]
=> 0
sample.has_milk = Reservation::Lunch.has_milks[:not_desired]
=> 0
sample.has_milk
=> "not_desired"

Enum,TrueとFalseの場合

# RDBではTinyIntに相当するものに使用する
enum has_milk: { # ミルクの希望
  desired: true, # 希望する
  not_desired: false, # 希望しない
}, _suffix: true
sample = Reservation::Lunch.find(2)
sample.has_milk
=> "desired"
sample.has_milk = Reservation::Lunch.has_milks[:not_desired]
=> false
sample.has_milk
=> nil

Rails enumの闇 整数値(integer)の代わりにbooleanを設定すると死ぬより抜粋

おそらく、enumがfalseが入ってきた時はnilに変換している?

カラム型TINYINTの場合にActiveRecord::Enumを使いたい

attribute :has_milk, ActiveRecord::Type::Integer.new

# ミルクの摂取の有無
enum has_milk: {
  desired: 1, # 希望する
  not_desired: 0, # 希望しない
}, _suffix: true
sample.has_milk
=> "desired"
Reservation::Lunch.has_milks[:desired]
=> 1
sample.has_milk = Reservation::Lunch.has_milks[:desired]
=> 1
sample.has_milk
=> "desired"
sample.has_milk = Reservation::Lunch.has_milks[:not_desired]
=> 0
sample.has_milk
=> "not_desired"

取得、保持とも期待通りの値が出ている(ほぼintegerじゃん)

とりあえず結論

  • booleanに対してEnumは使わない方が混乱を避けられる
  • 使用するのであれば、
attribute :has_milk, ActiveRecord::Type::Integer.new

ようなコードを記載し、integerとして扱えるようにする方が良いのかなと...
そもそもBooleanって2つじゃんと思いました

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away