0
votes

I have the following:

def create
  @product = Product.find(params[:product_id])
  @review = @product.reviews.build(params[:review])

if @review.save
  flash[:notice] = "Successfully created review."
    redirect_to product_url(@review.product_id)
else
  render new_product_review_path(@review.product_id)

end

end

My form is the following:

<% if @review.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@review.errors.count, "error") %> prohibited this product from being save</h2>
  <ul>
  <% review.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
  </ul>
</div>
<% end %>

<% form_for [@product, @review] do |f| %>
<p>
  <%= f.label :email, 'Email' %><br />
  <%= f.text_field :email %>
</p>
<p>
  <%= f.label :rating, 'Rating' %><br />
  <%= f.text_field :rating %>
</p>
<p>
  <%= f.label :comment, 'Comment' %><br />
  <%= f.text_area :comment, :rows => '12', :cols => 35 %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>

In the views/reviews I have a new.html.erb file which renders a form.

When I fail validation on that form I get

Template is missing

Missing template /products/1/reviews/new with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "/Users/myname/Sites/reviews/app/views",

How can I keep my errors so that they render in the form?

2

2 Answers

0
votes

Instead of:

render new_product_review_path(@review.product_id)

you may just use:

render :template => "reviews/new"

For further information about rendering, I suggest to read: http://edgeguides.rubyonrails.org/layouts_and_rendering.html

edit:

With usage of

render new_product_review_path(@review.product_id)

You want to render a template located in your filesystem here:

yourapp/views/products/1/reviews/new.html.erb

(see the missing template error given to you)

And I guess, correct path is:

yourapp/views/reviews/new.html.erb
0
votes

Change your create action to look like this

def create
  @product = Product.find(params[:product_id])
  @review = @product.reviews.build(params[:review])

  if @review.save
    flash[:notice] = "Successfully created review."
    redirect_to product_url(@review.product_id)
  else
    render :action => 'new'
  end
end

The render :action command is somewhat misleading as it is rendering the new.html.erb template within the current action NOT calling the new action.

This is done precisely so the view has the @product and @review objects in the state that was set by the form plus any changes that were made before the save failed. If you were to actually redirect to an action as you are trying to do then any form changes that had been made prior to the user hitting the create button would be lost. If you did this the flash message would still get displayed though as the flash is actually an alias to the session hash.