質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

解決済

1回答

950閲覧

結合テストがパスできない。 NoMethodError: undefined method `drinks' for nil:NilClass

divclass123

総合スコア35

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

0グッド

0クリップ

投稿2021/04/19 15:47

編集2021/04/19 16:22

実現したいこと、前提

自分でアプリを作っていて、
常設の商品が置いてあって
購入ページに行って、商品を購入するために必要な情報を入力して、購入ボタンをクリックしたら購入完了ページが表示される。と言った結合テストを書いてます。
そこのテストをパスしたいです。
詳しくは以下を参考にして欲しいのですが、
idが6番のuserに商品を投稿してもらって、user_idが6番の投稿は、常設の商品として、置いてあって、それ以外は一般ユーザーの投稿みたいなコードです。
イメージ説明

こんな感じで一般ユーザーの投稿と購入するページの商品の構造が一緒なので、クソコードになりました。

エラー内容

私の行った手順は以下です。

docker-compose exec web bundle exec rspec spec/system/trade_addresses_spec.rb

すると、以下のような結果になりました。

TradeAddresses 購入ができる時 必須項目を入力 (FAILED - 1) 購入ができない時 ログインしてないと購入ページに行っても、ログインページにリダイレクト 必須情報の抜け漏れ Failures: 1) TradeAddresses 購入ができる時 必須項目を入力 Failure/Error: @drinks = @admin_user.drinks.paginate(page: params[:page],per_page: 10) NoMethodError: undefined method `drinks' for nil:NilClass # ./app/controllers/sold_drinks_controller.rb:5:in `index' Finished in 2.78 seconds (files took 4.39 seconds to load) 3 examples, 1 failure Failed examples: rspec ./spec/system/trade_addresses_spec.rb:22 # TradeAddresses 購入ができる時 必須項目を入力 ERROR: 1

controllers/sold_drinks_controller.rb

class SoldDrinksController < ApplicationController def index @admin_user = User.find_by(id: 6) @drinks = @admin_user.drinks.paginate(page: params[:page],per_page: 10) @title = "商品を購入する" end end

のdrinksの中身が無いので起こってるエラーだと思います。

NoMethodError: undefined method `drinks' for nil:NilClass # ./app/controllers/sold_drinks_controller.rb:5:in `index'

該当のソースコード

私のgithubです

spec/system/trade_addresses_spec.rb

require 'rails_helper' RSpec.describe "TradeAddresses", type: :system do before do @user = FactoryBot.create(:user) @trade_address = FactoryBot.build(:trade_address) @admin_user = User.new(id: 6, email: "hoge@gmail.com", password: "hogehoge", password_confirmation: "hogehoge", activated: true) drinks = FactoryBot.build(:sold_drink,user_id: @admin_user.id) # @drinks = @admin_user.drinks.paginate(page: params[:page],per_page: 10) # NoMethodError: # undefined method `drinks' for nil:NilClass end context "購入ができる時" do it "必須項目を入力" do # ログイン visit login_path fill_in 'email', with: @user.email fill_in 'password', with: @user.password find('input[name="commit"]').click expect(current_path).to eq(user_path(@user)) expect(page).to have_content('商品を購入') # 商品一覧ページに遷移 visit buy_path # 購入ページに遷移 visit drink_trades(@drink) # その商品の写真が表示される # その商品の名前が表示される # その商品の値段が表示される # 必須項目を入力 fill_in 'card-number' ,with: '4242424242424242' fill_in 'card-exp-month' ,with: 12 fill_in 'card-exp-year' ,with: 24 fill_in 'card-cvc' ,with: 123 fill_in 'fam_name' ,with: @trade_address.fam_name fill_in 'first_name' ,with: @trade_address.first_name fill_in 'fam_name_kana' ,with: @trade_address.fam_name_kana fill_in 'first_name_kana' ,with: @trade_address.first_name_kana select '1960', from: 'trade_address[birthday(1i)]' select '8', from: 'trade_address[birthday(2i)]' select '19', from: 'trade_address[birthday(3i)]' fill_in 'postal-code' ,with: @trade_address.postal_code select '北海道', form: 'trade_address[prefecture]' fill_in 'postal-code' ,with: @trade_address.postal_code fill_in 'city' ,with: @trade_address.city fill_in 'addresses' ,with: @trade_address.address fill_in 'phone-number' ,with: @trade_address.phone_num # 購入するをクリック expect{ find('input[name="commit"]').click }.to change { Trade.count }.by(1) # 購入完了ページに遷移 expect(page).to have_content("商品をご購入いただきありがとうございます! ") end end

spec/factories/drinks.rb

FactoryBot.define do factory :drink do # class: モデル名 ってやる必要あるが、キー名で推測してるらしい name {"TOKYOロースト"} price {350} explain {"これはコーヒーの説明です"} region_id {2} body_id {Body.all.sample} acidity_id {Acidity.all.sample} processing_id {Processing.all.sample} likes_count {2} association :user association :region association :body association :acidity association :processing after(:build) do |drink| drink.image.attach(io: File.open('app/assets/images/ethiopia.jpg'), filename: 'ethiopia.jpg') end end factory :sold_drink ,class: Drink do name {"TOKYOロースト"} price {350} explain {"これはコーヒーの説明です"} region_id {2} body_id {Body.all.sample} acidity_id {Acidity.all.sample} processing_id {Processing.all.sample} likes_count {2} user_id {6} association :user association :region association :body association :acidity association :processing after(:build) do |drink| drink.image.attach(io: File.open('app/assets/images/ethiopia.jpg'), filename: 'ethiopia.jpg') end end end

controllers/sold_drikns_controller.rb

class SoldDrinksController < ApplicationController def index @admin_user = User.find_by(id: 6) @drinks = @admin_user.drinks.paginate(page: params[:page],per_page: 10) # ↑ここでエラーが起きてます。 @title = "商品を購入する" end end

試したこと

factory :sold_drink ,class: Drink do name {"TOKYOロースト"} price {350} explain {"これはコーヒーの説明です"} region_id {2} body_id {Body.all.sample} acidity_id {Acidity.all.sample} processing_id {Processing.all.sample} likes_count {2} user_id {6} association :user association :region association :body association :acidity association :processing after(:build) do |drink| drink.image.attach(io: File.open('app/assets/images/ethiopia.jpg'), filename: 'ethiopia.jpg') end end

このようにfactorybotを定義して、
user_idが6のdrinksは商品として登録されるので、このようなコードを書いたり、

spec/system/trade_addresses_spec.rb

@admin_user = User.new(id: 6, email: "hoge@gmail.com", password: "hogehoge", password_confirmation: "hogehoge", activated: true) drinks = FactoryBot.build(:sold_drink,user_id: @admin_user.id)

とかを定義したり、

@drink = Drink.new( name: "商品", price: 340, explain: "商品の説明", user_id: 6, image: ActiveStorage::Blob.create_and_upload!(io: File.open("app/assets/images/break_first.jpg"),filename: "breake_first.jpg") )

このように書いたら,user_idが6のdrink(商品)ができたので、
いけると思ったのですが、エラー内容は変わらずでした。

@admin_user => #<User:0x0000561921546128 id: 6, nickname: nil, email: "hoge@gmail.com", created_at: nil, updated_at: nil, password_digest: [FILTERED], remember_digest: nil, activation_digest: nil, activated: true, activated_at: nil>

@admin_userもしっかり定義されてるように感じます。

なお、私の環境は以下の通りです。
Docker version 20.10.5,mac catalina 10.15.7

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

@admin_user = User.create(id: 6, nickname: "hoge", email: "hoge@gmail.com", password: "hogehoge", password_confirmation: "hogehoge", activated: true) drinks = Drink.create( name: "商品", price: 340, explain: "商品の説明", user_id: 6, image: ActiveStorage::Blob.create_and_upload!(io: File.open("app/assets/images/break_first.jpg"),filename: "breake_first.jpg") )

と、User.newじゃなくて、User.createで上手くいきました。

投稿2021/04/19 16:24

divclass123

総合スコア35

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問