Reputation: 22643
I have a page which shows a book and it's many reviews. On this page there is also a form to write a new review and post it to the create action of the reviews controller. When you post the form, the id of the corresponding book gets sent also so that the relationship can be established correctly.
At the reviews controller, we attempt to save the review. Here is what my controller looks like:
def create
@review = current_user.reviews.build(params[:review])
@book = Book.find_by_ean params[:book]
@review.book = @book
if @review.save
redirect_to book_path(@book)
else
# In here I want to go back to book_path(@book), sending @review with it so that I can have access to @review.errors
end
end
Of course, when the review fails to save (review content is mandatory for example) I would like to go back to the book show page and display the form, along with errors to the user. Now as far as I can work out, there are 2 possibilities here:
What's the best way to solve this problem?
Upvotes: 1
Views: 713
Reputation: 21180
I usually solve this by sending the psot data to a member action in the original controller (in this case books) instead of a nested controller. For example:
# routes.rb
resources :books do
member do
post 'create_review'
end
end
And then in your view
# books/show.html.erb
<%= form_for @new_review, :url => create_review_book_path(@book) do |f| %>
...
<% end %>
And finally in your books controller
# books_controller.rb
def create_review
@book = Book.find(params[:id])
@new_review = @book.reviews.build(params[:review])
if @new_review.save
@new_review = Review.new
end
render :action => :show
end
What happens is that the form has been manually directed to post it's data to our new member route in the books controller. If the Review is successfully saved, then we assign a new review object to the variable in preparation for the next review. If it is not succesfull, then the @new_review variable will contain the errors which can be accessed in the form.
Upvotes: 2
Reputation: 1188
Well, you can't really pass an object through the get params (with a redirect) unless you serialize it and you don't want that.
I see two solutions for this problem. 1) Save the review in the books controller 2) Make the form submit via ajax and update the form in the review controller using "render :update"
I don't know which one is the best, this depents on the project specs like can you use ajax?
Upvotes: 0