【Ruby on Rails】to be valid, but got errors: User can’t be blank 【RSpec】が解決できなかった件

wood camera writing typography

今回私、こちらのエラーで死ぬほどひっかかりました。

※途中長々と書いてますが見当違いな事もあったので最後らへんまで飛ばす事をオススメします…

というのも、テックキャンプでの最終課題「商品出品機能」にて、

単体テストコードを実装するという事で、今までそんな詰まったことがなかったので

鼻をほじりながら作業をしていたのですが、めちゃくちゃにやられました。

得意の検索をしまくっても全くこれについての有力な情報がなかったので

今後困るであろう方たちの為に、自分が検索しまくったワードを下記に並べておきますね

(あとはここでハマったエラー群をもうがっつり貼っときます)

ーーー

Item

  商品出品機能

    できる時

      全て問題の無い状態であれば登録に成功する (FAILED – 1)

    できない時

      ○○だと出来ない

Failures:

  1) Item 商品出品機能 できる時 全て問題の無い状態であれば登録に成功する

     Failure/Error: expect(@item).to be_valid

       expected #<Item id: nil, item_name: “あああ”, description: “test”, category_id: 2, condition_id: 2, shipping_charge_id: 2, prefecture_id: 2, shipping_time_id: 2, price: 5000, user_id: nil, created_at: nil, updated_at: nil> to be valid, but got errors: User can’t be blank

     # ./spec/models/item_spec.rb:13:in `block (4 levels) in <top (required)>’

Finished in 0.16702 seconds (files took 0.89731 seconds to load)

2 examples, 1 failure

Failed examples:

rspec ./spec/models/item_spec.rb:12 # Item 商品出品機能 できる時 全て問題の無い状態であれば登録に成功する

ーーー

テストコード 単体 Rails できない

ActiveHash FactoryBot 連携方法

ActiveHash ファクトリーBOT エラー 解決できない

  factory :item do
    item_name { "あああ" }
    description {'test'}
    price {5000}
    category_id {2}
    condition_id {2}
    shipping_charge_id {2}
    prefecture_id {2}
    shipping_time_id {2}

ーーー

association :user テストコード 単体 エラー できない

Active Storage FactoryBot 成功しない 連携方法

ーーーーーーーーーー

さてさて、長くなりましたが、要は上での検索単語、自分が何をしたかったのか?どこにあたりをつけていたのか?です。

最終課題での商品出品機能には今までのテスト(ユーザー等)では違う要素がいくつかあります。

1、ActiveHashを使用している

2、Active Storageを使用している

3、ユーザー情報と連携している(user_id)

テストコードを実装する際、とりあえず「全て成功している状態」を作るのが第一です。

でなければその後に行う「全て成功したものから削ぎ落として失敗を作る」事ができないからです。

自分は今回、その部分でひっかかりました。

もちろん、手動でのDB登録はこの時点では成功しています。

でもテストコードで成功しない・・・上の3つを切り分けたいがどれがどれでどこから手をつけて良いのかわかりません・・・・

という事で、ここからはうだうだ書きません、上記の問題だと思っていた成功例を書きます。

1、ActiveHashについて

    category_id {2}
    condition_id {2}
    shipping_charge_id {2}
    prefecture_id {2}
    shipping_time_id {2}

みたいなのでOKです(カラム名は恐らく似通ってますが個々人で違うはずなので)

少し解説すれば、単純にActiveHashはIDでカテゴリ選択を行って判別してますので、それを入れてあげれば良いだけです。

2、Active Storageについて 

以下を記述

    after(:build) do |item|
      item.image.attach(io: File.open('public/images/timage.png'), filename: 'timage.png')
    end

3、ユーザー連携について
association :user と書いて @item = FactoryBot.build(:item)

ではなく

@item = FactoryBot.create(:item) と記述するで解決しました。

ーーー以下はそれでもわからない方向けの補足となります。

まずはコード構成ですが

/spec/models/item_spec.rb

require 'rails_helper'
RSpec.describe Item, type: :model do
  before do
    @item = FactoryBot.create(:item)
  end
  describe '商品出品機能' do
    context 'できる時' do
      it '全て問題の無い状態であれば登録に成功する' do
        expect(@item).to be_valid
      end
    end
    context 'できない時' do
      it '○○だと出来ない' do
      end
    end
  end
end

/spec/factories/items.rb

FactoryBot.define do
  factory :item do
    item_name { "あああ" }
    description {'test'}
    price {5000}
    category_id {2}
    condition_id {2}
    shipping_charge_id {2}
    prefecture_id {2}
    shipping_time_id {2}
    association :user 
    after(:build) do |item|
      item.image.attach(io: File.open('public/images/timage.png'), filename: 'timage.png')
    end
  end
end

これで一旦は通ります。

もっと補足というかアウトプット

今回の問題はbuildか?createか?というところが問題だったようです。

そもそも最初に検索ワードを羅列しましたが、実はすぐに

「user_idってどうすんねん、user_id{1}とかでもブランクになるしわからん・・」

となりましたが、教材にその部分の答えはあるのです。

/spec/factories/items.rb に association :user を入れろ、というものです。

ここまでは恐らく誰でもたどり着くのですが

この後が問題で、教材にはずーーとbuildと使われているのです。

だから問題だとすら思いませんでした。

エラーに直面したその日は顔真っ赤でActiveHashか???これのせいか?なんでだ?画像か?ユーザー連携か????

となってましたが次の日冷静にエラーを見れば

expected #<Item id: nil, item_name: “あああ”, description: “test”, category_id: 2, condition_id: 2, shipping_charge_id: 2, prefecture_id: 2, shipping_time_id: 2, price: 5000, user_id: nil, created_at: nil, updated_at: nil> to be valid, but got errors: User must exist, User can’t be blank

expected #<Item id: nil, item_name: “あああ”, description: “test”, category_id: 2, condition_id: 2, shipping_charge_id: 2, prefecture_id: 2, shipping_time_id: 2, price: 5000, user_id: nil, created_at: nil, updated_at: nil>

「ここまではデータとしてそれぞれ把握しましたよ」

to be valid, but got errors: User must exist, User can’t be blank

「全てマッチしませんね、なぜならuser_idが空だからです。と言われてます。」

その後、ふと目に止まったどっかの記事で

「必ずbuildではなくcreateにして下さい」という文面

その記事は全くの別問題の解決方法が書いてあったのでスルーしてましたが

まさかと思い自分のところを変えたらそのまま通りました・・・・長かった・・・

一応ですが、テストコードに於けるbuildとcreateの違いは

「DBにアクセスするかしないか?」だそうです、buildはアクセスしない為、速度が早いんだとか

今回、DBにアクセスする必要がある理由は、一度DBへ「user_idってそもそもどんな情報もってんの?」とカラムの確認をしにいっているようです。

その後、多分ですがこの前に行ったuserのテストコードへアクセスしています。

そのテストコードでは更にuserテストが実行され、全ての情報が問題ないと確認された後Itemに戻ってきます。

ここまでの情報が無いとuser_idはクリアできないんですねー

「ItemDBのuser_idカラムが数値で埋まってりゃいいんだろ!」とはいかないわけです。

ということで、長々となりましたが、誰かの役に立てば幸いです。


2021/08/10 追記 超恥ずかしい

上で色々言ってましたが、buildでもテストコードが通りました・・・

メンターさんから指摘がありましたが

バリデーションの段階でuesr_idを入れていた為、失敗していたようです。

それを消したあとに、buildに変更したところ成功しましたので、これも追記しておきます。

createじゃなくてbuildにした理由ですが

createだとテストする度にテストした結果がDBに書き込まれます。

どんどん無駄データが増えてしまうわけですね

今回バリデーションをuse_idにかけていたので、ユーザーデータまでテストする必要がありましたが

そこにバリデーションをかけていなければ、ユーザーデータまでテスト参照しなくて良いわけですね

あと、地味にコントローラーのnewの部分を

:newに変更したことも大きいですね

まだまだ、学ばなければいけないことが多そうです。

TECCAMP 残り55日 結婚式準備

結婚式の日とかってネットで言うのはどうなんだろう…?そのあたりのネットリテラシーが自分は少ないからなんともいえない

…ふむ、なんとなく書かないでおこう!

結婚式、あと少しなんです。

昨日は商品出品機能を実装…!したんですがテストコードでひっかかりました…

最後は負けを認めてメンターさんに質問して終了

本日答えの方向性を貰えるはずなので続きを実装したい

しかし!本日は結婚式場にきて試着と試食を行うので半日以上潰れるのです…

TECCAMP 残り61日 治った!

やはりケアは大事ですね

自分の時間の分配をもう少し考えないといけないなと感じました。

昨日の時間も18時間と中途半端だったのは、単純に「気分が乗らなかったから」ですね

まー…たまにはいいか!切り替え切り替え!

よし、地盤も固まったので、本日からまた少しづつ勉強を進めていこうかな!

TECCAMP 残り61日 気分

ちょっと最悪ですね

プログラミングやら勉強やら仕事とは別の事なので、そちらの事ではないのですが

なんとも、その気分のせいで仕事や勉強にも影響出るって感じの気分です。

「そういうこともある」ということでこういう時にどうしたら気分があがるか、少し考えて1日を過ごそうと思います。

TECCAMP 残り62日 プログラミングで稼ぐということ

自分はプログラマーではないのですが

プログラミングを始めようとしたキッカケは、このブログにも書きましたが

「効率化」です。

要は時間を作ることです。

Twitterとか意図的に見てると「稼ぐ」という単語をよく見かけますが、稼ぐ事にあまり興味が出ない…

でも今後はAIなどで、更なるデータの価値を生み出すというところで

プログラミングもいつか「効率化」の域からでるかもしれませんね

(なんかすごい良いこと言おうとしてTwitterで言った方がみんな見てくれそうなので文章力が力尽きた)

TECCAMP 残り63日 オリジナルアプリについて

転職活動に余裕ができたので、オリジナルアプリは最悪作らなくても大丈夫らしい

ただ、発表があるので作らないとだめなのかしら…?

そこらへんどうなってるのかわからない…ライフコーチに聞いてみよう

TECCAMP 残り64日 転職活動初回面談

さて、昨日やっと、本来techcampさんの元で行える転職活動の初回面談をしました。

結論からいうと、「転職活動支援期間はいつまでも延長可能」

とのこと、ヤッター!ヨカッター!これでまた

「じゃあシステム部から現場な^^」って言われても転職活動再開できる!

ということで、悩みのタネが一つ消えました!

これは本当にtechcampさん感謝!

TECCAMP 残り65日 ゲーミングチェア

到着しました、試座してきたかいがありました!

自分にとっては超絶フィットだけども、奥様が座りたいといっていたので座らせてあげたところ

「…はぁ、まぁ、なんかいいね!」

というリアクション、体格が違うとこうも違うかという感じですね!

TECCAMP 残り66日 1時間でも違う

昨日は30分といいつつ1時間だけやりました。

でもまだまだ足りない、今日は本当に3時間くらい割かないといけない

商品出品機能の実装、出来れば10時間程度で片付けたい、今までまとめたノートが役に立ってほしい

本日は東京の洗練、現状濃厚接触者なので、PCR検査に朝からいってきます。

TECCAMP 残り67日 まずは30分と決めた

9時からパソコンの前に座り、本当は18時だけど19時には解散するのループ

今はリモートだから時間多少あるけど、本社勤務だと往復2時間が無駄になりそう…

さて、状況は把握できたので

本日より30分だけでも勉強時間をとることにしました。

絶対、取る、よし、決めた!