DBに保存する前に一意かどうかを検証したい場合、バリデーションで uniqueness: true を使うと思いますが、presence: trueを併用しない場合(値がなくても良い場合)に少しつまづきました。
今回の問題
validates :hoge_code, uniqueness: true
このままだと、hoge_codeを何も入力せずに保存した場合、DBでデフォルトをnullにしていても空文字が入ってしまうんですよね。(int型の場合は0)
それで、次回以降また同じようにhoge_codeを入力せずに保存しようとした場合、先ほどの空文字「""」と同じと認識されてしまい、「その値は既に存在します」というバリデーションエラーになってしまいました。
解決:allow_blank オプションを追加
validates :hoge_code, uniqueness: true, allow_nil: true
これだとダメでしたが、
validates :hoge_code, uniqueness: true, allow_blank: true
こっちでいけました。
allow_nilだとnilしか許可してくれませんが、blankだとnilに加え空文字も含めた判断をしてくれるっぽい。
ActiveRecord側だけじゃなく、DBのnull周りも色々と複雑っぽいので、一度きちんと勉強したいな...と思いつつ。