[英]Ruby on Rails undefined method `destroy' for nil:NilClass
I'm having an issue while deleting user posts: 删除用户帖子时出现问题:
undefined method `destroy' for nil:NilClass nil:NilClass的未定义方法`destroy'
# 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. 现在,我发现我的错误是在引用方法“ correct_user”中的microposts_controller.rb文件中,因为它找不到微信的ID并返回nil。 And so we can't call the destroy method on nil object. 因此,我们无法在nil对象上调用destroy方法。 Can you please tell me why it is not finding the micropost id? 您能告诉我为什么找不到微博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
It looks the problem in your correct_user
method. 它看起来在您的correct_user
方法中的问题。 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" } %>
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
. 模型是MicroPost
,但控制器是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
. 您需要将控制器重命名为MicroPostsController
和它的文件micro_posts_controller.rb
。 Remove from routes.rb these 2 lines: 从routes.rb中删除以下两行:
post '/micro_posts', to: 'microposts#create'
delete '/micro_posts', to: 'microposts#destroy'
And change microposts
to micro_posts
(note the underscore) here: 并在此处将microposts
更改为micro_posts
(注意下划线):
resources :microposts, only: [:create, :destroy]
Use micro_post_path(micro_post)
for delete link in the view 使用micro_post_path(micro_post)
在视图中删除链接
Yep you have to set the value of @micropost beofre trying to destroy it. 是的,您必须设置@micropost beofre的值以尝试销毁它。 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. 通常,这是您想对params哈希进行的操作,因此您可以在destroy
方法开始时使用@micropost = Micropost.find(params[:id])
之类的东西。 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 :) 希望能帮助到你 :)
I think you should be passing the id param to your delete route in your view. 我认为您应该将id参数传递给视图中的删除路由。
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" } %>
试试这个: <%= link_to ' | Delete', micro_posts_path(micro_post.id), method: :delete , data: { confirm: "Are you sure" } %>
<%= link_to ' | Delete', micro_posts_path(micro_post.id), method: :delete , data: { confirm: "Are you sure" } %>
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. micro_posts_path
是一个收集路由,您需要使用带有资源ID的成员路由。 So in this scenario we remove s
from the route and it becomes micro_post_path
that is a member route. 因此,在这种情况下,我们从路由中删除s
,它成为成员路由的micro_post_path
。
I hadn't noticed that @zeitnot had answered before me with the same recommendation. 我没有注意到@zeitnot在我面前也提出了同样的建议。
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. 您没有传递对象ID,所以params[:id]
总是为零。
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 %>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.