我在rails应用程序中收到此错误undefined method 'comments'
。我知道我不应该使用> 1级嵌套资源,但在这种情况下我不知道如何应用正确的方法。
目前这是我的路线:
resources :performance_indicators do
resources :improvement_actions do
member do
put "like" => "improvement_actions#upvote"
put "unlike" => "improvement_actions#downvote"
end
resources :comments
end
end
正如我所说,我收到了这个错误:
NoMethodError in PerformanceIndicators#show
Showing .../app/views/comments/_form.html.erb where line #1 raised:
undefined method `comments' for nil:NilClass
我不知道我的问题是否在控制器中。有人可以帮忙吗? :)
修改
我的评论/ _form:
<%= form_for([@performance_indicator, @improvement_action, @improvement_action.comments.build]) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
这是我的CommentsController:
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :set_improvement_action
# GET /comments
# GET /comments.json
def index
end
# GET /comments/1
# GET /comments/1.json
def show
end
# GET /comments/new
def new
@comment = @improvement_action.comments.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
@comment = @improvement_action.comments.new(comment_params)
if @comment.save
format.html { redirect_to [@improvement_action.performance_indicator, @improvement_action], notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: [@improvement_action, @comment] }
else
format.html { render :new }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if @comment.update(comment_params)
format.html { redirect_to @comment, notice: 'Comment was successfully updated.' }
format.json { render :show, status: :ok, location: @comment }
else
format.html { render :edit }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
@comment.destroy
respond_to do |format|
format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
@comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:body)
end
def set_improvement_action
@improvement_action = ImprovementAction.includes(:comments).find(params[:improvement_action_id])
end
end
这是我的PerformanceIndicatorController:
class PerformanceIndicatorsController < ApplicationController
before_action :set_performance_indicator, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
# GET /performance_indicators
# GET /performance_indicators.json
def index
@performance_indicators = PerformanceIndicator.all
end
# GET /performance_indicators/1
# GET /performance_indicators/1.json
def show
#@performance_indicators = PerformanceIndicator.all.order("created_at DESC")
end
# GET /performance_indicators/new
def new
@performance_indicator = PerformanceIndicator.new
@comments = Comment.new
end
# GET /performance_indicators/1/edit
def edit
end
# POST /performance_indicators
# POST /performance_indicators.json
def create
@performance_indicator = PerformanceIndicator.new(performance_indicator_params)
respond_to do |format|
if @performance_indicator.save
format.html { redirect_to @performance_indicator, notice: 'Performance indicator was successfully created.' }
format.json { render :show, status: :created, location: @performance_indicator }
else
format.html { render :new }
format.json { render json: @performance_indicator.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /performance_indicators/1
# PATCH/PUT /performance_indicators/1.json
def update
respond_to do |format|
if @performance_indicator.update(performance_indicator_params)
format.html { redirect_to @performance_indicator, notice: 'Performance indicator was successfully updated.' }
format.json { render :show, status: :ok, location: @performance_indicator }
else
format.html { render :edit }
format.json { render json: @performance_indicator.errors, status: :unprocessable_entity }
end
end
end
# DELETE /performance_indicators/1
# DELETE /performance_indicators/1.json
def destroy
@performance_indicator.destroy
respond_to do |format|
format.html { redirect_to performance_indicators_url, notice: 'Performance indicator was successfully destroyed.' }
format.json { head :no_content }
end
end
def set_comment
@improvement_action = ImprovementAction.find(params[:improvement_action_id])
@comment = Comment.find(params[:id])
end
private
# Use callbacks to share common setup or constraints between actions.
def set_performance_indicator
@performance_indicator = PerformanceIndicator.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def performance_indicator_params
params.require(:performance_indicator).permit(:name, :numberTimesIdentifiedProblems, :numberTimesAnalysed)
end
end
答案 0 :(得分:0)
让我们从修复深层嵌套开始。
resources :performance_indicators, shallow: true do
resources :improvement_actions
end
resources :improvement_actions, only: [] do
member do
put "like" => "improvement_actions#upvote"
put "unlike" => "improvement_actions#downvote"
end
resources :comments
end
only: []
是一种聪明的技巧,可以在一个资源下嵌套路由,但会抑制路由的生成。我们想要,因为第一个块实际上声明了我们需要的所有路径。
Prefix Verb URI Pattern Controller#Action
performance_indicator_improvement_actions GET /performance_indicators/:performance_indicator_id/improvement_actions(.:format) improvement_actions#index
POST /performance_indicators/:performance_indicator_id/improvement_actions(.:format) improvement_actions#create
new_performance_indicator_improvement_action GET /performance_indicators/:performance_indicator_id/improvement_actions/new(.:format) improvement_actions#new
edit_performance_indicator_improvement_action GET /performance_indicators/:performance_indicator_id/improvement_actions/:id/edit(.:format) improvement_actions#edit
performance_indicator_improvement_action GET /performance_indicators/:performance_indicator_id/improvement_actions/:id(.:format) improvement_actions#show
PATCH /performance_indicators/:performance_indicator_id/improvement_actions/:id(.:format) improvement_actions#update
PUT /performance_indicators/:performance_indicator_id/improvement_actions/:id(.:format) improvement_actions#update
DELETE /performance_indicators/:performance_indicator_id/improvement_actions/:id(.:format) improvement_actions#destroy
performance_indicators GET /performance_indicators(.:format) performance_indicators#index
POST /performance_indicators(.:format) performance_indicators#create
new_performance_indicator GET /performance_indicators/new(.:format) performance_indicators#new
edit_performance_indicator GET /performance_indicators/:id/edit(.:format) performance_indicators#edit
performance_indicator GET /performance_indicators/:id(.:format) performance_indicators#show
PATCH /performance_indicators/:id(.:format) performance_indicators#update
PUT /performance_indicators/:id(.:format) performance_indicators#update
DELETE /performance_indicators/:id(.:format) performance_indicators#destroy
like_improvement_action PUT /improvement_actions/:id/like(.:format) improvement_actions#upvote
unlike_improvement_action PUT /improvement_actions/:id/unlike(.:format) improvement_actions#downvote
improvement_action_comments GET /improvement_actions/:improvement_action_id/comments(.:format) comments#index
POST /improvement_actions/:improvement_action_id/comments(.:format) comments#create
new_improvement_action_comment GET /improvement_actions/:improvement_action_id/comments/new(.:format) comments#new
edit_improvement_action_comment GET /improvement_actions/:improvement_action_id/comments/:id/edit(.:format) comments#edit
improvement_action_comment GET /improvement_actions/:improvement_action_id/comments/:id(.:format) comments#show
PATCH /improvement_actions/:improvement_action_id/comments/:id(.:format) comments#update
PUT /improvement_actions/:improvement_action_id/comments/:id(.:format) comments#update
DELETE /improvement_actions/:improvement_action_id/comments/:id(.:format) comments#destroy
取消资源嵌套意味着可以通过很少的环节来跳过。
class CommentsController < ApplicationController
before_action :set_improvement_action
# GET /improvement_actions/:improvement_action_id/comments/new
def new
@comment = @improvement_action.comments.new
end
# POST /improvement_actions/:improvement_action_id/comments
def create
@comment = @improvement_action.comments.new(comment_params) do |c|
# @todo - you should associate comment with the user who created it at some point.
# c.author = current_user
end
# note that you where saving the record twice!
if @comment.save
format.html { redirect_to [@improvement_action.performance_indicator, @improvement_action], notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: [@improvement_action, @comment] }
else
format.html { render :new }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
# ...
private
def comment_params
params.require(:comment).permit(:body)
end
def set_improvement_action
@improvement_action = ImprovementAction.includes(:comments)
.find(params[:improvement_action_id])
end
end
如果可能,您应该在控制器端使用新记录处理播种。
<%= form_for([@improvement_action, @comment]) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>