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

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

ただいまの
回答率

89.87%

いいね機能実装中にエラー(NoMethodError)が発生しました

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 72

ikdnaht

score 3

前提・実現したいこと

ruby on rails 初学者です。
写真投稿アプリを制作中、
いいね機能の実装の際にエラーメッセージが発生しました。

現状、deviseを導入した上で、
likeテーブルを作り、
自分がいいねをしていない場合は「いいね」、
いいねをしている場合は「いいねを取り消す」という処理にしたいです。

こちらの記事を参考にしました。
https://eiji-hb.hatenablog.com/entry/2019/10/23/151224

発生している問題・エラーメッセージ

NoMethodError in Posts#index

undefined method `id' for nil:NilClass

該当のソースコード

app/view/posts/index.html.haml

.post_lists
  - @posts.each do |post|
    %div.post_content
      %div.post_content__upper_box
        %div.post_content__upper_box__name
          = link_to post.user.name, user_path(post.user), class: "post_content__upper_box__username"
        - if user_signed_in? && current_user.id == post.user_id
          = link_to "投稿を削除", post_path(post.id), method: :delete, class: "post_content__upper_box__delete"
      = image_tag post.image.url, class: "post_content__image"
      %div.post_content__rower_box
        %div.post_content__rower_box__caption
          = post.text
        %div.post_content__rower_box__like
          -if current_user.likes.find_by(post_id: @post.id)
            = link_to 'いいね!を取り消す', post_like_path(@post), method: :delete
          -else
            = link_to 'いいね!', post_likes_path(@post), method: :post

app/config/routes.rb

Rails.application.routes.draw do
  devise_for :users
  root to: 'posts#index'

  resources :users, only: [:index, :show]
  resources :posts, only: [:index, :new, :create, :destroy] do
    resources :likes, only: [:create, :destroy]
  end
end


app/controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :authenticate_user!, only: [:show, :new]

  def index
    @posts = Post.includes(:user).order(created_at: :DESC)
    @like = Like.new
  end

  def show
    @post = Post.find(params[:id])
  end

  def new
    @posts = Post.new
  end

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to root_path
    else
      render :new
    end
  end

  def destroy
    post = Post.find(params[:id])
    post.destroy
    redirect_to root_path
  end

  private
  def post_params
    params.require(:post).permit(:image, :text).merge(user_id: current_user.id)
  end

end


app/controllers/likes_controller.rb

class LikesController < ApplicationController
  before_action :set_post, only: [:create, :destroy]
  def create
    @like = current_user.likes.create(like_params)
    redirect_to root_path(@post)
  end

  def destroy
    @like = Like.find_by(like_params, user_id: current_user.id)
    @like.destroy
    redirect_to root_path(@post)
  end

  private
  def set_post
    @post = Post.find(params[:post_id])
  end

  def like_params
    params.permit(:post_id)
  end
end


app/controllers/users_controller.rb

class UsersController < ApplicationController

  def index
    @users = User.all
  end

  def show
    @user = User.find(params[:id])
    @posts = @user.posts
  end

end

試したこと

app/view/posts/index.html.haml内の条件分岐、「-if current_user.likes.find_by(post_id: @post.id)」以下において、post_idが取れていないことが原因かと考え、routes.rbのネストができているか確認をしてみました。

補足情報(FW/ツールのバージョンなど)

Rails 5.2.4.1
ruby 2.5.1

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

controllerのエラーの様な表示ですが多分viewの方ですね。
viewに @post というのがあります。複数形の@postsは定義されていますが単数形は定義されていません。ので @post.id で掲示のエラーになります。
@のない、post.id の間違いだと思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/06 13:30

    2)に関しては、likes_controllerのcreateアクションにredirect_to root_pathを入れているからでしょうか?いいねをした後に、root_pathのPost#indexページに戻したいという意図で、記述してしまっています。

    rails routesこちらです

    Prefix Verb URI Pattern Controller#Action
    new_user_session GET /users/sign_in(.:format) devise/sessions#new
    user_session POST /users/sign_in(.:format) devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
    new_user_password GET /users/password/new(.:format) devise/passwords#new
    edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
    user_password PATCH /users/password(.:format) devise/passwords#update
    PUT /users/password(.:format) devise/passwords#update
    POST /users/password(.:format) devise/passwords#create
    cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
    new_user_registration GET /users/sign_up(.:format) devise/registrations#new
    edit_user_registration GET /users/edit(.:format) devise/registrations#edit
    user_registration PATCH /users(.:format) devise/registrations#update
    PUT /users(.:format) devise/registrations#update
    DELETE /users(.:format) devise/registrations#destroy
    POST /users(.:format) devise/registrations#create
    root GET / posts#index
    users GET /users(.:format) users#index
    user GET /users/:id(.:format) users#show
    post_likes POST /posts/:post_id/likes(.:format) likes#create
    post_like DELETE /posts/:post_id/likes/:id(.:format) likes#destroy

    キャンセル

  • 2020/01/06 15:23

    すみません、お手上げです。
    前の方に似たような宣言があって、そちらに引っ張られてるってのを想定したのですがありませんでした。

    キャンセル

  • 2020/01/06 16:56

    そうでうか。
    ありがとうございます!エラーに対するアプローチの仕方など、勉強になりました!もう少しコードを見て、調べてみます!

    キャンセル

check解決した方法

0

app/view/posts/index.html.hamlを下記のようにすることで、暫定的にですが、エラーの解消ができました。

.post_lists
  - @posts.each do |post|
    %div.post_content
      %div.post_content__upper_box
        %div.post_content__upper_box__name
          = link_to post.user.name, user_path(post.user), class: "post_content__upper_box__username"
        - if user_signed_in? && current_user.id == post.user_id
          = link_to "投稿を削除", post_path(post.id), method: :delete, class: "post_content__upper_box__delete"
      = image_tag post.image.url, class: "post_content__image"
      %div.post_content__rower_box
        %div.post_content__rower_box__caption
          = post.text
        %div.post_content__rower_box__like
          - like = current_user.likes.find_by(post_id: post.id)
          - if like != nil
            = link_to 'いいね!を取り消す', post_like_path(post,like), method: :delete
          - else
            = link_to 'いいね!', post_likes_path(post), method: :post

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.87%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る