Rails 6からだけれど、モデルのエラー確認にof_kind?
メソッドが使えるらしい。
最初は、伊藤さんのQiitaの記事を見て、be_added
メソッドを知った。これも便利そうだなぁと思っていたのだが、そのコメント欄にRails 6からof_kind?
が加わったと書いてあった。
どちらもめっちゃ便利じゃないですか。
今までどうしていたか?
すごく昔は、エラー数だけカウントして済ましていたけれど、最近はcontain_exactly
メソッドを使っていた。
expect(subject.errors.details[:name]).to contain_exactly({ error: :blank })
これでもまぁ割と簡潔には書けているようには見える…けれど、contain_exactly
は完全一致しないといけないので、他の値が入ってくるようなケースだと辛い。
# valueとかcountとか書くのが、かなり面倒… expect(subject.errors.details[:code_name]).to contain_exactly( { error: :blank }, { count: 3, error: :too_short }, { error: :invalid, value: nil }, )
今後はどうするか?
これを、of_kind?
で書き換えると…
# valueやcountが不要になって簡潔! expect(subject.errors).to be_of_kind(:code_name, :blank) expect(subject.errors).to be_of_kind(:code_name, :invalid) expect(subject.errors).to be_of_kind(:code_name, :too_short)
コード量が増えているようには見えますが、行コピーして最後だけ書き換えるだけなので楽です。
既存のコードを書き換える正規表現
いちいち手で書き換えていくのが面倒なので、正規表現を作りました。RubyMine上で置換するのに使ったらちゃんと動きました。
# 検索条件 expect\(subject.errors.details\[(.+?)\]\)\.to contain_exactly\(\{.*?error: ([:\w]+)(.*?) \}\) # 置換する文字列 expect(subject.errors).to be_of_kind($1, $2)
単純なやつ
Before
これが…
expect(subject.errors.details[:name]).to contain_exactly({ error: :blank })
After
こう置換されます。
expect(subject.errors).to be_of_kind(:name, :blank)
ちょっと複雑なやつ
Before
これが…
expect(subject.errors.details[:name]).to contain_exactly({ error: :invalid, value: nil })
After
こう置換されます。
expect(subject.errors).to be_of_kind(:name, :invalid)
まとめ
of_kind?
メソッドを使うと検証が簡潔になっていい!ただし、Rails 6から!
あと、kind_of
と間違えがちになるので気をつけたいところ…。