重构嵌套路由,如何解决这个 redirect_to?

Refactoring nested routes, how do I address this redirect_to?

我正在为一个我一直在做的项目做作业。我刚刚被介绍重构我的嵌套路线。以下是更改。

routes.rb

   resources :topics do 
     resources :posts, except: [:index] do
       resources :comments, only: [:create, :destroy]
     end
   end

  resources :topics do
    resources :posts, except: [:index]
  end

  resources :posts, only: [] do
    resources :comments, only: [:create, :destroy]
  end

之后我的指示如下:

Run rake routes to see how this changes routing. Then make the following changes to refactor with these new, shallower routes:

Change the comment paths, in both the comments/_comment.html.erb and the comments/_form.html.erb partials.

Change the CommentsController actions so that they no longer initialize @topic.

Derive @topic from @post because we still want redirect_to the @post page after creating or destroying a comment. Furthermore, @post is still nested under @topic.

Visit posts, then delete and create comments to test this new shallow nesting.

rake 路线

▶ rake routes
                  Prefix Verb   URI Pattern                                Controller#Action
         comments_create GET    /comments/create(.:format)                 comments#create
        new_user_session GET    /users/sign_in(.:format)                   devise/sessions#new
            user_session POST   /users/sign_in(.:format)                   devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)                  devise/sessions#destroy
           user_password POST   /users/password(.:format)                  devise/passwords#create
       new_user_password GET    /users/password/new(.:format)              devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)             devise/passwords#edit
                         PATCH  /users/password(.:format)                  devise/passwords#update
                         PUT    /users/password(.:format)                  devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)                    devise/registrations#cancel
       user_registration POST   /users(.:format)                           devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)                   devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)                      devise/registrations#edit
                         PATCH  /users(.:format)                           devise/registrations#update
                         PUT    /users(.:format)                           devise/registrations#update
                         DELETE /users(.:format)                           devise/registrations#destroy
       user_confirmation POST   /users/confirmation(.:format)              devise/confirmations#create
   new_user_confirmation GET    /users/confirmation/new(.:format)          devise/confirmations#new
                         GET    /users/confirmation(.:format)              devise/confirmations#show
                    user PATCH  /users/:id(.:format)                       users#update
                         PUT    /users/:id(.:format)                       users#update
             topic_posts POST   /topics/:topic_id/posts(.:format)          posts#create
          new_topic_post GET    /topics/:topic_id/posts/new(.:format)      posts#new
         edit_topic_post GET    /topics/:topic_id/posts/:id/edit(.:format) posts#edit
              topic_post GET    /topics/:topic_id/posts/:id(.:format)      posts#show
                         PATCH  /topics/:topic_id/posts/:id(.:format)      posts#update
                         PUT    /topics/:topic_id/posts/:id(.:format)      posts#update
                         DELETE /topics/:topic_id/posts/:id(.:format)      posts#destroy
                  topics GET    /topics(.:format)                          topics#index
                         POST   /topics(.:format)                          topics#create
               new_topic GET    /topics/new(.:format)                      topics#new
              edit_topic GET    /topics/:id/edit(.:format)                 topics#edit
                   topic GET    /topics/:id(.:format)                      topics#show
                         PATCH  /topics/:id(.:format)                      topics#update
                         PUT    /topics/:id(.:format)                      topics#update
                         DELETE /topics/:id(.:format)                      topics#destroy
           post_comments POST   /posts/:post_id/comments(.:format)         comments#create
            post_comment DELETE /posts/:post_id/comments/:id(.:format)     comments#destroy
                   about GET    /about(.:format)                           welcome#about
                    root GET    /                                          welcome#index

_comment.html.erb

<% @comments.each do |comment| %>

<div class="media">
  <div class="media-left">
    <%= image_tag(comment.user.avatar.small.url, class: "media-object") if comment.user.try(:avatar) %>
  </div>
  <div class="media-body">
    <small>
      <% comment.user.name %> commented <%= time_ago_in_words(comment.created_at) %> ago
      <% if policy(comment).destroy? %>
        | <%= link_to "Delete", [@topic, @post, comment], method: :delete %>
      <% end %>
    </small>
    <p><%= comment.body %>
  </div>
</div>
<% end %>

我特意把第11行改成:

| <%= link_to "Delete", [@post, comment], method: :delete %>

_form.html.erb

<%= form_for [topic, post, comment] do |f| %>
  <% if comment.errors.any? %>
    <div class="alert alert-danger">
      <h4>There are <%= pluralize(comment.errors.count, "error") %>.</h4>
      <ul>
        <% comment.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
    <% end %>

    <div class="form-inline">
    <%= form_group_tag(comment.errors[:body]) do %>
      <%= f.label :body %>
      <%= f.text_field :body, class: 'form-control'%>
    <% end %>

    <div class="form-group">
      <%= f.submit "Comment", class: 'btn btn-default' %>
    </div>
  </div>
  <% end %>

第一行我改成了:

<%= form_for [post, comment] do |f| %>

现在我可以在启动 Rails 服务器时查看项目。我不确定我将如何进行这最后一步。

Derive @topic from @post because we still want redirect_to the @post page after creating or destroying a comment. Furthermore, @post is still nested under @topic.

这是我的comments_controller.rb

class CommentsController < ApplicationController
  def create
    # find topic by id
    # @topic = Topic.find(params[:topic_id])
    # find post id through topic
    @post = Post.find(params[:post_id])
    # comments on post
    @comments = @post.comments

    @comment = current_user.comments.build(params.require(:comment).permit(:body, :post_id))
    @comment.post = @post


    authorize @comment
    if @comment.save
      flash[:notice] = "Comment was created."
      redirect_to [@topic, @post]
    else
      flash[:error] = "Error saving the comment. Please try again."
      # must render the the page calling the form!!
      render 'posts/show'
    end
  end

  def new

  end

  def destroy
    @topic = Topic.find(params[:topic_id])
    @post = @topic.posts.find(params[:post_id])
    @comment = @post.comments.find(params[:id])

    authorize @comment
    if @comment.destroy
      flash[:notice] = "Comment was removed."
      redirect_to [@topic, @post]
    else
      flash[:error] = "Comment couldn't be deleted. Try again."
      redirect_to [@topic, @post]
    end
  end
end

如您所见,我显示帖子的路径是

topic_post GET    /topics/:topic_id/posts/:id(.:format)      posts#show

当我被告知要删除 @topic 初始化时,我应该如何执行此操作?我试图将它包含在我当前修改的代码中,但在尝试删除评论时收到此错误。

Processing by CommentsController#destroy as HTML
  Parameters: {"authenticity_token"=>"ocCSra0R/kcA+5MHVowZDNShghHhNUKYcO3yJaDuUKcZsRab90who4SuOK4MmS/4XXhycK0XZJ1UbS/n09aFEg==", "post_id"=>"2", "id"=>"7"}
  Topic Load (0.1ms)  SELECT  "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT 1  [["id", nil]]
Completed 404 Not Found in 7ms (ActiveRecord: 0.6ms)

此致。

Derive @topic from @post because we still want redirect_to the @post page after creating or destroying a comment. Furthermore, @post is still nested under @topic.

它是说不是通过 Topic.find 加载主题,而是从 post 获取主题。 topic_id 不再在 params 中,因此您必须从 post 中获取它。没什么大不了的,因为每个 post 都有一个主题,对吧?这必须是真实的,否则不可能使您的路线更浅。

像这样:

def destroy
  @post = Post.find(params[:post_id])
  @topic = @post.topic
  # ... the rest I think is unchanged
end

如果您真的想要,您可以完全删除 @topic,只需在重定向中执行此操作即可:

redirect_to [@post.topic, @post]