I want to create a like function, but the foreign key is not referenced, so it becomes undefined method `id' for nil: NilClass

Asked 2 years ago, Updated 2 years ago, 49 views

When I tried to implement the like function and pressed the post button, I tried to transition to the post list page, but I got an error on the like button.
I used this article as a reference.
Rails Create a mini app with like features

The code stuck in the error is as follows

default_like?(post)
    self.likes.exists?(post_id:post.id)
  end

The error message is as follows:

NoMethodError in Posts#index

undefined method `id' for nil —NilClass

Therefore, when I commented out the code in the source code in question, the error disappeared and I could press like, but this time I couldn't cancel it.
I don't know what to do.

user.rb (user model)

class User<ApplicationRecord
  # Include default device modules.Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  device:database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
    
  has_one_attached —image
  has_many —Comments       
  has_many —posts
  has_many:like,dependent::destroy
  has_many:liked_posts, through::likes,source::
 
  default_like ?(post)
    self.likes.exists?(post_id:post.id)
  end


  with_options presence —true do
    validates —nickname
    validates —mania_history
    values:enjoy_point
    validates:email
    values:password,length: {minimum:6}
  end
end

post.rb (posting model)

class Post <ApplicationRecord
    has_many_attached —images
    belongs_to —user
    has_many —like
    has_many:like_users,through::like,source::user


    values:content, presence:true

end

like.rb (like feature model)

class Like <ApplicationRecord
 belongs_to —post
 belongs_to —user
end

Below is the controller related to like function

class LikeController<ApplicationController
  def create
    @like=current_user.likes.create(post_id:params[:post_id])
    redirect_back(fallback_location:root_path)
  end

  def destroy
    @like=Like.find_by (post_id:params[:post_id], user_id:current_user.id)
    @like.destroy
    redirect_back(fallback_location:root_path)
  end
end

Below is the controller for posting

class PostsController<ApplicationController
  before_action:authenticate_user!, only:[:new,:update,:create,:edit,:update,:destroy]
  before_action: find_post, only: [:edit,:update,:show,:destroy]

    def index
        @posts=Post.all
        @like=Like.new
      end

      def new
        @post=Post.new
        @like=Like.new

      end

    def show
    end
    
    
    def create
      @post=current_user
      @post=Post.create(post_params)
      [email protected]
        redirect_to root_path, notice: 'Post Successful'
        else
          redirect_to new_post_path, notice: 'Post failed'
        end
      end
    
      default
      end

      default update
        @post.update(post_params)
      end

      def destroy
        [email protected] store
          redirect_to root_path, alert: 'Post deleted'
        else
          redirect_to root_path
        end
      end

      private

        def post_params
          param.require(:post).permit(:content, {images:[]}).merge(user_id:current_user.id)
        end

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

        def force_redirect_unless_my_post
          return redirect_to root_path, alert: 'You do not have permissions' [email protected]!=current_user
        end
end

Below is the view

<div class="content-wrapper">
    <div class="content-block">
        <%@posts.each do | post | %>
        <div class="content">
         <div class="user-about">
             <div class="image">
             <%if post.user.image.attached?%>
             <%=image_tagpost.user.image%>
                <%else%>
            <%=image_tag no.user.png%>
                <%end%>
             </div>

         <div class="profile">
            <div class="name-history">
                <div class="name">

                <%=post.user.nickname%>


                </div>
                <div class="mania-history">
                    <%="Learning history: #{post.user.mania_history} years"%>
                </div>
             </div>
             
             <div class="enjoy-point">
             <%="Fun Points#{post.user.enjoy_point}"%>
             </div>
         </div>
       </div>
       
       <div class="text">
        <p><%=post.content%>/p>
    </div>
        <%if post.images.attached?%>
        <%post.images.each do | image | %>
            <div class='images'>
                <%=image_tag image%>
            </div>
        <%end%>
        <%end%>
         <div class="action-menu">
            <%if user_signed_in?%>
             <div class="like">
             <h3>Number of likes: <%=post.likes.count%>/h3>
             <div class='like-button'>
                <%if current_user.already_liked?(post.id)%>
                <%=button_to 'unlike', post_like_path(post), method::delete%>
             <%else%>
               <%=Button_to 'Like', post_like_path(post)%>
             <%end%>

            </div>
            </div>
            <%end%>
             <div class="comment">
                 
        </div>
         </div>

        </div>
        <%end%>


    </div>
    <div class="sidebar">
     <div class="box">

     </div>
     <div class="box">
         
    </div>
    </div>
</div>

As I pointed out,
in line 48 of view <%if current_user.already_liked?(post.id)%> to
<%if current_user.already_liked?(@post)%> but there was no change.
The other thing is that controller strong parameters related to like functionality

@like=current_user.likes.create(post_id:params[:post_id])

to

@like=current_user.likes.create(post_id:post_id)

I changed it to , but nothing changed.
Maybe it's because the like controller doesn't have a new method.

def new
    @like=Like.new
  end

After adding , I also added a new method to routes.rb, and deleted the description from the controller of the post, so the error changed to the following:

ActionController::UrlGenerationError in Posts#index

No route matches {:action=>"destroy",:controller=>"likes",:post_id=>#<Postid:1, content:"asdf", created_at:"2021-03-26 23:40:56", updated_at:"2021-03-26 23:40:56", updated_at:"2021-03-26:40:56;killing}

post.id seems to have been acquired, but I thought I could not because I received all the information, but I don't know the next action plan.

ruby-on-rails ruby

2022-09-30 19:43

2 Answers

I referred to this article.
[Rails] Complete Like functionality!Synchronization Like, Display Like Count, Asynchronous Like, Icon Display, Summarize how to implement each

Also, the description of the view file (like function) is

<%if user_signed_in?%>
  <div class="like">
    <h3>Number of likes: <%=post.likes.count%>/h3>
    <div class='like-button'>
      <%if current_user.like_by?(post.id)%>
        <td><%=link_to 'unlike', destroy_like_path(post), class: "like-link", method:: DELETE%></td>
         <i class="fa fa-heart unlike-btn">/i>
      <%else%>
         <td><%=link_to 'like', create_like_path(post), class: "like-link", method::create%></td>
         <i class="fa fa-heart like-btn">/i>
      <%end%>

User Model Description

 defliked_by?(post_id)
  likes.where(post_id:post_id).exists?
end

I changed it to , and it was resolved.


2022-09-30 19:43

The already_liked? method expects instances of the Post class to be passed to arguments.

default_like?(post)
  self.likes.exists?(post_id:post.id)
end

On the other hand, the original view passed an integer to the already_liked? method.

<%if current_user.already_liked?(post.id)%>

So there's something wrong with this part already.It must be aligned with either.For example, in the article you are referring to, the Post class instance is passed over.

The view that was added as "Tried" passed @post instead of post.

<%if current_user.already_liked?(@post)%>

For PostsController #index, @posts exists, but @post does not exist. You should pass post.


2022-09-30 19:43

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.