前提・実現したいこと
現在既存のアプリ(カフェ登録ができるようなアプリ)に対していいね機能を実装したのですが
ローカル環境ではいいね機能もしっかり機能していたのでrspecでテストを行ったところ
タイトルのエラーが発生しました。
恐らくcurrent_userがnilだとはいうことだと思いますがイマイチ現状なぜエラーが発生しているのか
掴めていません。
ちなみにログイン機能を実装した際はgem 'devise'は使用していません。
そのためかcurrent_userが使用できないのかと考えてはいましたが他の箇所でもcurrent_userを
使用していました。
application_controller.rbではdef current_userで定義してあります。
またrspecにてbeforeでログインしていないという動作を怠ったということも考えましたが
ちゃんとログインするような記述はしておりました。
どなたか原因特定できる方もしいましたらご教授お願い致します。
発生している問題・エラーメッセージ
1) Caves #show カフェ詳細画面の表示に成功すること Failure/Error: <% if current_user.already_liked?(@cafe) %> ActionView::Template::Error: undefined method `already_liked?' for nil:NilClass # ./app/views/caves/show.html.erb:73:in `_app_views_caves_show_html_erb__3062244970416319179_74500' # ./spec/requests/caves_spec.rb:45:in `block (3 levels) in <main>' # ------------------ # --- Caused by: --- # NoMethodError: # undefined method `already_liked?' for nil:NilClass # ./app/views/caves/show.html.erb:73:in `_app_views_caves_show_html_erb__3062244970416319179_74500'
該当のソースコード
<% provide(:title, "cafe") %> <%= render "shared/login_header" %> <div class="detail_title">カフェ詳細</div> <div class="cafe_detail"> <p class="img_detail"> <% if @cafe.image? %> <%= image_tag @cafe.image.to_s %> <% else %> <p>画像なし</p> <% end %> </p> <div class="cafe_description"> <p class="cafe_item"> <strong> <i class="fas fa-store"></i>店名: </strong> <%= @cafe.name %> </p> <p class="cafe_item"> <strong> <i class="fas fa-map-marker"></i>住所: </strong> <%= @cafe.address %> </p> <%= render 'shared/cafe_map', cafe: @cafe %> <p class="cafe_item"> <strong> <i class="fas fa-clock"></i>営業時間: </strong> <%= @cafe.business_hours.strftime( "%H:%M" ) %>~<%= @cafe.end_business_hours.strftime( "%H:%M" ) %> </p> <p class="cafe_item"> <strong> <i class="fas fa-lightbulb"></i>コンセント席数: </strong> <%= @cafe.number_seats %>席 </p> <p class="cafe_item"> <strong> <i class="fas fa-wifi"></i>Wifi: </strong> <% if @cafe.wifi == true %> <%= @cafe.wifi="◯" %> <% else %> <%= @cafe.wifi="×" %> <% end %> </p> </div> <div class="detail_link"> <%= link_to '更新する', edit_cafe_path(@cafe) %> | <%= link_to '戻る', caves_path %> </div> </div> <div class="detail_comment">コメント一覧</div> <div class="comment_space"> <% @comments.each do |c| %> <div class="user_comment"> <a href="/users/<%= @cafe.user_id %>"><%= c.user.email %></a> <%= c.content %> <hr> </div> <% end %> <div class="comment_button"> <%= form_for [@cafe, @comment] do |f| %> <%= f.text_field :content %> <br> <%= f.submit 'コメントする' %> <% end %> </div> </div> <div class="like_space"> <div class="like_number">いいね件数: <%= @cafe.likes.count %></div> <% if current_user.already_liked?(@cafe) %> <%= button_to 'いいねを取り消す', cafe_like_path(@cafe), method: :delete %> <% else %> <%= button_to 'いいね', cafe_likes_path(@cafe) %> <% end %> </div>
class CavesController < ApplicationController before_action :set_cafe, only: [:show, :edit, :update, :destroy] # GET /caves or /caves.json def index @q = Cafe.ransack(params[:q]) @caves = @q.result(distinct: true).page(params[:page]).per(8) end # GET /caves/1 or /caves/1.json def show @cafe = Cafe.find(params[:id]) @comments = @cafe.comments @comment = Comment.new @like = Like.new end # GET /caves/new def new @cafe = Cafe.new end # GET /caves/1/edit def edit end # POST /caves or /caves.json def create @cafe = Cafe.new(cafe_params) @cafe.user_id = current_user.id respond_to do |format| if @cafe.save format.html { redirect_to @cafe, notice: "登録しました" } format.json { render :show, status: :created, location: @cafe } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @cafe.errors, status: :unprocessable_entity } end end end # PATCH/PUT /caves/1 or /caves/1.json def update respond_to do |format| if @cafe.update(cafe_params) format.html { redirect_to @cafe, notice: "更新しました" } format.json { render :show, status: :ok, location: @cafe } else format.html { render :edit, status: :unprocessable_entity } format.json { render json: @cafe.errors, status: :unprocessable_entity } end end end # DELETE /caves/1 or /caves/1.json def destroy @cafe.destroy respond_to do |format| format.html { redirect_to caves_url, notice: "削除しました" } format.json { head :no_content } end end private def set_cafe @cafe = Cafe.find(params[:id]) end def cafe_params params.require(:cafe).permit(:image, :name, :address, :business_hours, :end_business_hours, :number_seats, :wifi, :user_id, :latitude, :longitude, :content) end end
class User < ApplicationRecord has_secure_password has_many :likes has_many :caves, dependent: :destroy has_many :like_caves, through: :likes, source: :cafe has_many :comments VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+.[a-z]+\z/i.freeze validates :email, { presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false } } VALID_PASSWORD_REGEX = /\A[\w\-]+\z/.freeze validates :password, { presence: true, length: { minimum: 8 }, format: { with: VALID_PASSWORD_REGEX }, allow_nil: true } validates :password_confirmation, presence: true def already_liked?(cafe) likes.exists?(cafe_id: cafe.id) end end
require 'rails_helper' RSpec.describe "Caves", type: :request do describe "#new" do let(:cafe) { create(:cafe) } let(:user) { create(:user) } before do session_params = { session: { email: user.email, password: user.password } } post "/login", params: session_params end it 'カフェ登録画面の表示に成功すること' do get '/caves/new' expect(response).to have_http_status(200) end end describe "#create" do let(:cafe) { create(:cafe) } let(:user) { create(:user) } before do session_params = { session: { email: user.email, password: user.password } } post "/login", params: session_params end it 'カフェ作成に成功すること' do valid_params = { image: cafe.image, name: cafe.name, address: cafe.address, number_seats: cafe.number_seats } expect { post '/caves/new', params: { cafe: valid_params } } expect(response).to have_http_status(200) end end describe "#show" do let(:cafe) { create(:cafe) } let(:user) { create(:user) } before do session_params = { session: { email: user.email, password: user.password } } post "/login", params: session_params end it 'カフェ詳細画面の表示に成功すること' do get "/caves/#{cafe.id}" expect(response).to have_http_status(200) end end describe "#edit" do let(:cafe) { create(:cafe) } let(:user) { create(:user) } before do session_params = { session: { email: user.email, password: user.password } } post "/login", params: session_params end it 'カフェ編集画面の表示に成功すること' do get "/caves/#{cafe.id}/edit" expect(response).to have_http_status(200) end end describe "#update" do let(:cafe) { create(:cafe) } let(:user) { create(:user) } before do session_params = { session: { email: user.email, password: user.password } } post "/login", params: session_params end it 'カフェの編集に成功すること' do get "/caves/#{cafe.id}/edit" valid_params = { image: cafe.image, name: cafe.name, address: cafe.address, number_seats: cafe.number_seats } expect { put "/caves/#{cafe.id}", params: { cafe: valid_params } } expect(response).to have_http_status(200) end end end
class ApplicationController < ActionController::Base helper_method :current_user def login? if current_user.nil? redirect_to login_path, alert: "ログインが必要です。" end end def already_login? unless current_user.nil? redirect_to user_path, notice: "ログイン済みです。" end end def current_user if session[:user_id] current_user ||= User.find(session[:user_id]) end current_user end end
試したこと
controllerのshowの箇所に@user = current_user.idの記載をしてみましたが
idがnilにエラーメッセージは変更されました。
gemで'devise'を使用していないことが原因のようにも感じております。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/14 12:11