重构嵌套路由,如何解决这个 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]
我正在为一个我一直在做的项目做作业。我刚刚被介绍重构我的嵌套路线。以下是更改。
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]