title: how to implement a recursive deletion in ruby on rails ?
body: <p>I'm making an app in ruby on rails, similar to <code>Reddit</code>, along the project I decided to use recursion on the <code>Comment</code> model using a <code>polymorphic association</code>.  </p>
  
  <p>Recursive deletion Article &lt;- Comment &lt;- Comment and so on</p>
  
  <p>The problem is that when I delete the Article, which comments depends and using <code>:delete_all</code> (or <code>:destroy</code>, already tried that) on the <code>has_many</code> association, it will only delete the first level of comments.<br>
  The same way happens to the <code>Comments</code>, only the first level of replies gets deleted, and I really dont want orphan comments out there.</p>
  
  <p>The question is, how can I implement a recursive deletion in this context?  </p>
  
  <p><strong>models/article.rb:</strong></p>
  
  <pre><code>class Article &lt; ActiveRecord::Base
    belongs_to :user
    has_and_belongs_to_many :tags
    has_many :comments, as: :commentable , :dependent =&gt; :delete_all
  end
  </code></pre>
  
  <p><strong>models/comment.rb:</strong></p>
  
  <pre><code>class Comment &lt; ActiveRecord::Base
    belongs_to :user
    belongs_to :commentable, polymorphic: true
    has_many :comments, as: :commentable , :dependent =&gt; :delete_all
  end
  </code></pre>
  
  <p><strong>articles_controller.rb:</strong></p>
  
  <pre><code>def destroy
      @article = Article.find(params[:id])
      @comments = @article.comments.destroy
      @article.destroy
  
      redirect_to articles_path
  end
  </code></pre>
  
  <p><strong>comments_controller.rb:</strong></p>
  
  <pre><code>class CommentsController &lt; ApplicationController
  before_action :find_commentable
                      .
                      .
                      .
      def create
        @comment = @commentable.comments.new(comment_params)
  
        if @comment.save
          redirect_to :back, notice: 'Your comment was successfully posted!'
        else
          redirect_to :back, notice: "Your comment wasn't posted!"
        end
      end
  
      private
  
      def comment_params
        params.require(:comment).permit(:body, :user_id)
      end
  
      def find_commentable
        @commentable = Comment.find_by_id(params[:comment_id]) if params[:comment_id]
        @commentable = Article.find_by_id(params[:article_id]) if params[:article_id]
      end
  end
  </code></pre>
  
  <p><strong>views/articles/show.html.erb</strong></p>
  
  <pre><code>.
  .
  .
  &lt;ul&gt;
    &lt;%= render(partial: 'comments/comment', collection: @article.comments) %&gt;
  &lt;/ul&gt;
  </code></pre>
  
  <p><strong>views/comments/_comment.html.erb</strong></p>
  
  <pre><code>&lt;li&gt;
    &lt;%= comment.body %&gt; -
    &lt;small&gt;Submitted &lt;%= time_ago_in_words(comment.created_at) %&gt; ago by &lt;%= User.find(comment.user_id).name %&gt;&lt;/small&gt;
  
    &lt;%= form_for [comment, Comment.new] do |f| %&gt;
        &lt;%= f.hidden_field(:user_id , :value =&gt; current_user.id) %&gt;
        &lt;%= f.text_area :body, placeholder: "Add a Reply", required: true %&gt;&lt;br/&gt;
        &lt;%= f.submit "Reply"  %&gt;
        &lt;% end %&gt;
    &lt;ul&gt;
        &lt;%= render partial: 'comments/comment', collection: comment.comments %&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  </code></pre>