Rendering different controller actions in Rails when using resource-oriented controllers
Say I'm making a Q&A site like StackOverflow. I have two resources: Question and Answer. I'm using default Rails RESTful resource routes, so each resource has its own controller and methods for creating it.
In the /questions/show
view, I want to allow the user to submit an answer for the particular question. The form will POST to /answers
, which will get routed as a request to the AnswersController
with a call to the create
method.
If the answer was created, I can simply redirect back to the original question. However, I'm running into trouble dealing with validation failures on the answer object. I need to render the /question/show
view and show the validation errors for the answer object. It's开发者_Python百科 not clear to me how to best do this.
Here are example snippets of what the two controllers might look like.
class AnswersController < ApplicationController
def create
@answer = Answer.new(params[:answer])
if @answer.save
redirect_to @answer.question
else
# What should go here??
end
end
end
class QuestionsController < ApplicationController
def show
@question = Question.find(params[:id])
@answer = Answer.new(:question_id => @question.id)
end
end
What should go in the else clause of the AnswersController
's create method? A redirect seems wrong, since the error is really caused by the same request. Calling something like render :template => 'questions/show'
seems wrong too, since I have to initialize any instance variables that the template depends on.
This style of having separate actions for calling GET to view the form for creating an object and calling POST to actually create the object seems to work well within a single controller.
How can it be done across controllers?
Try this on for size. It redirects, but passes back the dodgy answer object full of errors.
class AnswersController < ApplicationController
def create
@answer = Answer.new(params[:answer])
# stash the dodgy answer if it failed to save
session[:answer] = @answer unless @answer.save
redirect_to @answer.question
end
end
class QuestionsController < ApplicationController
def show
@question = Question.find(params[:id])
# if we have one stashed in the session - grab it from there
# because it probably contains errors
@answer = session[:answer] || Answer.new(:question_id => @question.id)
end
end
Some details need adding (eg clearing it from the session when done) etc
精彩评论