-2

User has many comments, comment belongs to many users. How do I fix this error?

undefined method `first_name' for nil:NilClass

when I try to do

   <h3>Comments</h3>
     <% @guide.comments.each do |comment| %>
       <div>
         <p><%= comment.user.first_name %></p>
       </div>
     <% end %>

user.rb

has_many :comments

comment.rb

class Comment < ActiveRecord::Base
  belongs_to :user
end

comments migration (I added a user_id column):

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.text :body
      t.integer :user_id

      t.timestamps
      add_foreign_key :comments, :guides
    end
  end
end

comments controller:

def create
    @comment = Comment.new(comment_params)

    respond_to do |format|
      if @comment.save
        format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
        format.json { render action: 'show', status: :created, location: @comment }
      else
        format.html { render action: 'new' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end
Dylan Richards
  • 708
  • 1
  • 13
  • 33

6 Answers6

1

long time ago but this could be usefull for someone with the same error. you should delegate the first_name to the user and allow nil

class Comment < ActiveRecord::Base
  belongs_to :user
  delegate :first_name, to: :user, allow_nil: true, prefix: true
end

then call it in you view with

<h3>Comments</h3>
  <% @guide.comments.each do |comment| %>
    <div>
      <p><%= comment.user_first_name %></p>
    </div>
  <% end %>

if there is no user, then it will be display nothing and not raise an exception

rob
  • 2,136
  • 8
  • 29
  • 37
0

I'm guessing that you did not set the user id while creating the comment object. can you try the following code?

def create
    @comment = current_user.comments.new(comment_params)

    respond_to do |format|
      if @comment.save
        format.html { redirect_to @comment, notice: 'Comment was successfully created.' }
        format.json { render action: 'show', status: :created, location: @comment }
      else
        format.html { render action: 'new' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end
arun15thmay
  • 1,062
  • 1
  • 9
  • 19
  • @DylanRichards the problem is that you have comments that do not belong to a user. Clear your database first and then try again with the above code. – Mischa Jan 03 '14 at 13:02
  • @DylanRichards Can you check your database if the user_id is not nil for the comments?? – arun15thmay Jan 03 '14 at 13:02
  • @arun15thmay instead of merging params you could simply do: `current_user.comments.build(comment_params)`. Much cleaner IMHO. – Mischa Jan 03 '14 at 13:03
  • There are no comments in the database. Not sure how user_id would be nil then. Give me a second to run the above code again. – Dylan Richards Jan 03 '14 at 13:05
  • @DylanRichards If there are no comments, it shouldn't even go into the iteration and you wouldn't get that error. You must be doing *something* wrong, but from what you're showing us I cannot determine what exactly. – Mischa Jan 03 '14 at 13:29
  • @DylanRichards As far as I can see, that controller part of you code is definitely wrong. Try creating new comments and check if it works. – arun15thmay Jan 03 '14 at 13:30
0

Ensure that you user model has a first_name attribute. Then confirm that your comment record (s) actually have a user associated with them. You may not have the user_id column whitelisted in the Comment class, so the user is not set

class Comment
  attr_accessible :user_id, ...
end

Or in rails 4 you have strong parameters instead of attr_accessible

How is attr_accessible used in Rails 4?

Community
  • 1
  • 1
S.Spencer
  • 581
  • 3
  • 8
  • I'm permitting that in my params hash. – Dylan Richards Jan 03 '14 at 13:07
  • I would use the console to investigate what attributes you have set on the comments. `rails c` `Comment.first` ensure you do have user_id set. OR check them all `Comment.all.map(&:user_id)` – S.Spencer Jan 03 '14 at 13:11
  • Or even more concisely `Comment.pluck(:user_id)`. Any nil values are telling that the foreign key is not getting set. – S.Spencer Jan 03 '14 at 13:19
  • `Comment.pluck(:user_id)` is returning an empty array. – Dylan Richards Jan 03 '14 at 13:20
  • If you don't have any comment records, then this should not occur. Are you getting the error when using the default development environment? Just ensuring you are not troubleshooting separate development and production databases. If you are still stuck, delete the databases and start again. Ensure you have a clean slate. – S.Spencer Jan 03 '14 at 13:25
0

Model didn't find comment.user. It may be the comment's user_id havn't been set or the user_id didn't apper in "user" table "id" column. You can print the comment id and comment.user_id and check in DB.

Do you set:

has_many :comments, :dependent => :destroy

Or it could hapeen you delete the user but the user's comments remain, then for these comments, comment.user is null.

lalameat
  • 754
  • 3
  • 10
0

Are you sure your user_id is set when you create a comment ? Maybe this simple line is missing in your controller

    @comment.user = current_user

In order to be sure to have a user in your comment, you should add in your Comment model

validates_presence_of :user_id

and in your User model

has_many :comments, :dependent => :destroy
Mkou
  • 525
  • 4
  • 12
-1

Defining methods in Ruby is very simple. To solve your problem, define

class << nil
  def first_name; "John" end
  def last_name; "Doe" end
end

And the error will disappear. All the nil objects are now named "John Doe".

Boris Stitnicky
  • 12,444
  • 5
  • 57
  • 74