i'mtrying a simple feature where a user can comment on inquest post , but comment .user.username is not working ,it's rendering comment.user but does not support user attributes
create_table "comments", force: :cascade do |t|
t.string "content"
t.integer "inquest_id"
t.integer "user_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["inquest_id"], name: "index_comments_on_inquest_id"
t.index ["user_id"], name: "index_comments_on_user_id"
end
comment_model
class Comment < ApplicationRecord
belongs_to :inquest
belongs_to :user
end
user_model is simple with has many comments association
comments create method of controller
def create
@comment = Comment.new(comment_params)
pp comment_params
@inquest = Inquest.find(params[:inquest_id])
@comment = Comment.new(comment_params)
@comment.inquest = @inquest
@comment.user = current_user
respond_to do |format|
if @comment.save
format.js do
@inquest = Inquest.find(params[:inquest_id])
end
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end
I'm rendering comments in inquest's show.html.erb
Showing /Users/zunairaihsan/Desktop/fyp_ed_bolt/app/views/inquests/show.html.erb
where line #123 raised:
undefined method `user_name' for nil:NilClass
I've tried most of the ways possible , but it's not working.please let me know where I'm wrong
CodePudding user response:
I assume, in inquests/show.html.erb
you're displaying multiple comments, something like
<%= @inquest.comments.each do |comment| %>
<%= comment.user.user_name %>
<%= comment.content %>
<% end %>
Many comments will render without issue. Comment
model and database doesn't allow user_id
to be nil
.
But looks like one comment's user_id
doesn't have a corresponding id
in users table. When you try to figure out what's going on and remove user_name
<%= @inquest.comments.each do |comment| %>
<%= comment.user %>
<%= comment.content %>
<% end %>
Sneaky broken comment probably doesn't show you anything, comment.user
is nil
, and because you have no validation on comment.content
it could also be nil
.
First, get rid of comments without user
to verify this is the issue:
# this is fast enough for a few thousand comments
>> Comment.find_each { |comment| comment.destroy unless comment.user }
After this inquests/show.html.erb
should be working.
To make sure this doesn't happen again:
class User
# this will delete all `user.comments` when you destroy `user`
has_many :comments, dependent: :destroy
# ...
end
To really make sure this doesn't happen again:
class CreateComment < ActiveRecord::Migration[7.0]
def change
create_table :comments do |t|
t.references :user, null: false, foreign_key: true
# ...
end
end
end
With foreign_key
constraint, your database will not let you destroy a user if they have comments. This works in tandem with dependent: :destroy
. If you delete a user and rails automatically destroys all user.comments
, then database will not complain.
Probably do the same for inquest
as well if it's not optional.
Also comments without content
are not really comments:
class Comment < ApplicationRecord
belongs_to :inquest
belongs_to :user
validates :content, presence: true
end
CodePudding user response:
On line 123 of .../fyp_ed_bolt/app/views/inquests/show.html.erb, the object comment.user is nil, so there is no one method user_name for a nil object.