ruby 如何让destroy方法为Rails中的嵌套资源工作?

pkbketx9  于 2023-02-15  发布在  Ruby
关注(0)|答案(2)|浏览(132)

目前正在学习Ruby on Rails并创建一个带有评论的简单博客应用程序。我有一个Comment模型和一个Article模型。Comment是多态的,两个模型都有很多评论。
我尝试提出一个destroy方法,它能够同时删除属于CommentArticle的评论(并且保留为[已删除],而不破坏它们的子评论,很像Reddit,尽管我还没有看到这一部分)。
我尝试过不同的路径,但还没有找到正确的路径,嵌套路径仍然让我有点困惑,我不确定在创建link_to时如何传递路径请求的参数。
这些是我的文件
routes.rb:

Rails.application.routes.draw do

  get 'comments/new'
  get 'comments/create'
  get 'articles/index'
  get 'articles/show'
  root 'articles#index'

resources :articles  do 
    resources :comments
end
resources :comments do 
    resources :comments
end

end

article.rb:

class Article < ApplicationRecord
    has_many :comments, as: :commentable
end

comment.rb:

class Comment < ApplicationRecord
    belongs_to :commentable, polymorphic: :true
    has_many :comments, as: :commentable
end

评论_控制器.rb:

class CommentsController < ApplicationController
before_action :find_commentable

  def new
    @comment = Comment.new
  end

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

    if @comment.save
        redirect_back(fallback_location: root_path)
    else
        redirect_back(fallback_location: root_path)
    end
  end 

  def destroy
    @comment = @commentable.comments.find(params[:id])
    @comment.destroy
    redirect_back(fallback_location: root_path)
  end

  private
  def comment_params
    params.require(:comment).permit(:body)
  end

  def find_commentable
    if params[:article_id]
      @commentable = Article.find_by_id(params[:article_id])
    elsif params[:comment_id]      
      @commentable = Comment.find_by_id(params[:comment_id])
    end
  end

end

show.html.erb,其中属于Article.rb的注解的格式为:

<h1> <%= @article.title %> </h1>
<p> <%= @article.body %> </p>
<small>Submitted <%= time_ago_in_words(@article.created_at) %> ago </small> <br/>

<h3>Comments</h3>

<%= form_for [@article, Comment.new] do |f| %>
    <%= f.text_area :body, placeholder: "Say something!" %> <br/>
    <%= f.submit "Submit" %>
<% end %>

<ul class="parent-comment">
    <%= render partial: 'comments/comment', collection: @article.comments %>
</ul>

<%= link_to "Index", articles_path %>

部分_comment.html.erb显示了属于这篇文章的评论以及属于其他评论的评论,我尝试在这里集成link_to

<p> <%= comment.body %> </p>
<small>Submitted <%= time_ago_in_words(comment.created_at) %> ago </small> <br/>

<%= form_for [comment, Comment.new] do |f| %>
    <%= f.text_area :body, placeholder: "Add a reply!" %><br/>
    <%= f.submit "Reply" %>
    <%= link_to "Delete", comment_path(comment), method: :delete %>
<% end %>

<ul>
    <%= render partial: 'comments/comment', collection: comment.comments %>
</ul>

每当我似乎找到了正确的路径,NoMethodError in CommentsController#destroy — undefined methodcomments' for nil:NilClass就出现了。为什么控制器会显示它为未定义?据我所知,它在new`方法中工作。
你能不能给予我一些指导,告诉我该怎么做,或者我应该修复什么?我也不知道如何删除家长的评论,而且我还没有找到适合这种情况的信息。如果你知道该给我指哪里,我会全力以赴的。
谢谢你。

9jyewag0

9jyewag01#

因为您的设计模型结构。
您的观点

<%= link_to "Delete", comment_path(comment), method: :delete %>

您的find_commentable

elsif params[:comment_id]      
         @commentable = Comment.find_by_id(params[:comment_id])
   end

@commentable将是一个Comment类,因此它不会像Article类那样具有.comments方法

yrefmtwq

yrefmtwq2#

仔细检查以破坏方法

def destroy
    @comment = @commentable.comments.find(params[:id])
    @comment.destroy
    redirect_back(fallback_location: root_path)
  end

使用@comment = @commentable.comments.find_by(id: params[:id])并检查@comment是否有值?
只要添加一个这样的条件,它就不会抛出错误:

@comment.destroy if @comment

如果@commentnil并且试图销毁,则它将抛出错误。

相关问题