Reputation: 15
I'm having an issue while deleting user posts:
undefined method `destroy' for nil:NilClass
# routes.rb
Rails.application.routes.draw do
get 'sessions/new'
get 'users/new'
get 'user/new'
root to:'pages#home'
get '/home', to:'pages#home'
get '/help', to:'pages#help'
get '/about', to:'pages#about'
get '/contact', to:'pages#contact'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
post '/micro_posts', to: 'microposts#create'
delete '/micro_posts', to: 'microposts#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :microposts, only: [:create, :destroy]
end
# microposts_controller.rb
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: [:destroy]
def create
@micropost = current_user.micro_posts.build(req_params)
if @micropost.save
flash[:success] = "Post created"
redirect_to root_url
else
@feed_items = []
render 'pages/home'
end
end
def destroy
@micropost.destroy
flash[:success] = "Post deleted"
redirect_to request.referrer || root_url
end
private
def req_params
params.require(:micro_post).permit(:content)
end
def correct_user
@micropost = current_user.micro_posts.find_by_id(params[:id])
redirect_to root_url if @micropost.nil?
end
end
# _micro_post.html.erb file
<li id="micropost" ><%= micro_post.id %>
<%= link_to gravatar_for(micro_post.user, size: 50), micro_post.user %>
<span class="user" ><%= link_to micro_post.user.name, micro_post.user %></span><br/>
<span class="content" ><%= micro_post.content %></span>
<br/>
<span class="timestamp">
posted <%= time_ago_in_words(micro_post.created_at) %> ago
<% if current_user?(micro_post.user) %>
<%= link_to ' | Delete', micro_posts_path, method: :delete , data: { confirm: "Are you sure" } %>
<% end %>
</span>
<br/>
</li>
Now what I figured out is that my error is in microposts_controller.rb file in the reference method "correct_user", because it could not find the id of the micropost and returning nil. And so we can't call the destroy method on nil object. Can you please tell me why it is not finding the micropost id?
Started DELETE "/micro_posts" for 127.0.0.1 at 2019-02-21 21:43:17 +0500
(0.7ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
↳ C:/Ruby25-x64/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
Processing by MicropostsController#destroy as HTML
Parameters: {"authenticity_token"=>"aNeBnIy/JOrWz+sQdzU2w06faILW2dM+f8SPwmXVmJs1XfJ8OqbkgPVwkpoY/HBjh8YJhVPWZ4BC1Onxg0AtWw=="}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/helpers/sessions_helper.rb:16
MicroPost Load (0.3ms) SELECT "micro_posts".* FROM "micro_posts" WHERE "micro_posts"."id" IS NULL LIMIT ? [["LIMIT", 1]]
↳ app/controllers/microposts_controller.rb:36
Completed 500 Internal Server Error in 56ms (ActiveRecord: 1.9ms)
NoMethodError (undefined method `destroy' for nil:NilClass):
app/controllers/microposts_controller.rb:22:in `destroy
Upvotes: 1
Views: 1573
Reputation: 269
I hadn't noticed that @zeitnot had answered before me with the same recommendation.
I think your issue is your delete link not referencing the actual object. You're not passing the object id, so params[:id]
is always going to be nil.
Try this to see if it works:
<% if current_user?(micro_post.user) %>
<%= link_to ' | Delete', micro_post_path(micro_post), method: :delete , data: { confirm: "Are you sure" } %>
<% end %>
Upvotes: 0
Reputation: 1314
Try this:
<%= link_to ' | Delete', micro_post_path(micro_post), method: :delete , data: { confirm: "Are you sure" } %>
The issue is that you are using a collection route. micro_posts_path
is a collection route and you need to use a member route which takes resource id. So in this scenario we remove s
from the route and it becomes micro_post_path
that is a member route.
Upvotes: 0
Reputation: 4640
If you don't mind, I'll convert my comments to the answer, to not leave the question unanswered.
You have a naming issue. The model is MicroPost
, but the controller is MicropostsController
. That's why you're trying to create custom routes.
You need to rename controller to MicroPostsController
and it's file to micro_posts_controller.rb
. Remove from routes.rb these 2 lines:
post '/micro_posts', to: 'microposts#create'
delete '/micro_posts', to: 'microposts#destroy'
And change microposts
to micro_posts
(note the underscore) here:
resources :microposts, only: [:create, :destroy]
Use micro_post_path(micro_post)
for delete link in the view
Upvotes: 1
Reputation: 15372
It looks the problem in your correct_user
method. Try to remove it and use this way:
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :set_micropost, only: :destroy
...
def set_micropost
@micropost ||= Micropost.find params[:id]
end
end
And in your view:
<%= link_to ' | Delete', @micropost, method: :delete , data: { confirm: "Are you sure" } %>
Upvotes: 1
Reputation: 1772
I think you should be passing the id param to your delete route in your view.
Instead of this:
<%= link_to ' | Delete', micro_posts_path, method: :delete , data: { confirm: "Are you sure" } %>
Try this:
<%= link_to ' | Delete', micro_posts_path(micro_post.id), method: :delete , data: { confirm: "Are you sure" } %>
Upvotes: 0
Reputation: 152
Yep you have to set the value of @micropost beofre trying to destroy it.
Usually this is something you want to do with the params hash so you could have sth like @micropost = Micropost.find(params[:id])
at the beginning of your destroy
method. This is a line you might want to use in other methods in you controller so you can refactor it as follow
class MicropostsController < ApplicationController
before_action :set_micropost, only: [:destroy]
...
private
def set_micropost
@micropost = Micropost.find(params[:id])
end
end
Hope it helps :)
Upvotes: 0