nullを理解していなかった話

内容が間違えていたので、修正しました

nullを理解しておらず、はまりました。

null

  • 未定義であるということ
  • 数字の0や空白とは違う

はまったこと

migrationのnot null制約は生成時のvalidationになります。

migrationのnot null制約は値がnullかどうかの判断になります。

対して、モデルのvalidatesは、保存時にないといけないという制約になります。

モデルのpresence: trueは、値が存在するかどうかの判断になります。

似ているけど、役割が違うということ。

Speaker classのmigration fileになります。

class CreateSpeakers < ActiveRecord::Migration
  def change
    create_table :speakers do |t|
      t.string :name, null: false
      t.string :type

      t.timestamps null: false
    end
  end
end

nameはnot nullなんで、存在しないといけないから、次のようなテストは通るだろ?と考えてしまっていました。

FactoryGirl.define do
  factory :player do
    name Faker::Name.name
  end
end
require 'rails_helper'

RSpec.describe Player, type: :model do
  describe 'validation' do
    let(:player) { create(:player) }

    it 'nameは存在しないといけない' do
      player.name = ''
      expect(player).not_to be_valid
    end
  end
end

これだとテストは通りません。

なぜなら、生成後の変更の存在はnot nullという条件ではないからです。

理由は**''がnilではなく、値として認識されているからです。

''.nil?
=> false
''.present?
=> false

なので、素直にpresence: trueを書かないといけません。

class Player < Speaker
  validates :name, presence: true
end

これでテストが通ります。

違いがわかっておけば怖くない。

nullを全く理解していなかった話です。

個人的にrailsから入ったエンジニアは、sqlの知識が弱いと勝手に思っています。

sqlの知識をもっと身につけないとなー