Chema Mora Chema Mora - 6 months ago 24
Ruby Question

Rails : undefined method `user_id=' for nil:NilClass

I am running into a problem with the Comments controller in my blog. Every time I tried to create a new comment I have an

undefined method "user_id=" for nil:NilClass
, and it doesn't create the comment. It happens the same when I try to destroy one, I have
undefined method "comments" for #<User:0x007fe2c872f968>
.

When I restart the server, the comment I created shows up, but it doesn't happen the same with the destroy method.

I am not sure what is happening here, I have to be doing something wrong with the user but I cannot find where is the problem.

Posts Controller

class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]

def index
@posts = Post.all.order('created_at DESC')
@posts = Post.paginate(:page => params[:page])
end

def new
@post = Post.new
end

def create
@post = Post.new(post_params)

if @post.save
redirect_to @post
else
render "new"
end

end

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

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

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

if @post.update(params[:post].permit(:title, :body, :image))
redirect_to @post
else
render 'edit'
end
end

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

redirect_to posts_path
end

private

def post_params
params.require(:post).permit(:title, :body, :image)
end

end


Comments Controller

class CommentsController < ApplicationController
before_action :correct_user, only: :destroy

def create
@post = Post.find(params[:post_id])
@comments = @post.comments.create(params[:comment].permit(:name, :body))
@comment.user_id = current_user.id
comment.save

redirect_to post_path(@post)
end

def show
@post = Post.find(params[:post_id])
@comments = @post.comments.create(params[:comment])
end

def destroy
@post = Post.find(params[:post_id])
@comments = @post.comments.find(params[:id])
@comments.destroy

redirect_to post_path(@post)
end


private

def comment_params
params.require(:commet).permit(:user_id, :name, :body)
end

def correct_user
@comment = current_user.comments.find_by(id: params[:id])
if @comment.nil?
flash[:alert] = "Not your comment!"
redirect_to :back
end
end
end


Schema

ActiveRecord::Schema.define(version: 20160515190759) do

create_table "average_caches", force: :cascade do |t|
t.integer "rater_id"
t.integer "rateable_id"
t.string "rateable_type"
t.float "avg", null: false
t.datetime "created_at"
t.datetime "updated_at"
end

create_table "comments", force: :cascade do |t|
t.string "name"
t.text "body"
t.integer "post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end

add_index "comments", ["post_id"], name: "index_comments_on_post_id"

create_table "overall_averages", force: :cascade do |t|
t.integer "rateable_id"
t.string "rateable_type"
t.float "overall_avg", null: false
t.datetime "created_at"
t.datetime "updated_at"
end

create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.string "image_url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
end

create_table "rates", force: :cascade do |t|
t.integer "rater_id"
t.integer "rateable_id"
t.string "rateable_type"
t.float "stars", null: false
t.string "dimension"
t.datetime "created_at"
t.datetime "updated_at"
end

add_index "rates", ["rateable_id", "rateable_type"], name: "index_rates_on_rateable_id_and_rateable_type"
add_index "rates", ["rater_id"], name: "index_rates_on_rater_id"

create_table "rating_caches", force: :cascade do |t|
t.integer "cacheable_id"
t.string "cacheable_type"
t.float "avg", null: false
t.integer "qty", null: false
t.string "dimension"
t.datetime "created_at"
t.datetime "updated_at"
end

add_index "rating_caches", ["cacheable_id", "cacheable_type"], name: "index_rating_caches_on_cacheable_id_and_cacheable_type"

create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

Answer

All simple, you have two different instance objects. Also, You have already comment_params method, just use that one for secure it.

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(comment_params.merge(user_id: current_user.id))    
    redirect_to post_path(@post)
  end
Comments