Reputation: 12018
Im writing a blog engine, So I have a post view (show.html.erb) that shows a post, comments list and a comments form.
I call the form this way:
<%= render :partial => 'comments/form', :locals => {:comment => @post.comments.new} %>
Im not sure if passing the comment that way is correct, but at least I get the post_id on the new comment.
This is my form (_form.html.erb on comments view):
<%= form_for comment, :action => "create" do |f| %>
<% if comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(comment.errors.count, "error") %> prohibited this comment from being added:</h2>
<ul>
<% comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :post_id %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :email %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :url %>
<%= f.text_field :url %>
</p>
<p>
<%= f.label :content %>
<%= f.text_area :content %>
</p>
<p class="no-border">
<%= f.submit "Post", :class => "button" %>
</p>
<% end %>
And this the action:
def create
@comment = Comment.new(params[:comment])
respond_to do |format|
if @comment.save
format.html { redirect_to :back }
else
format.html { redirect_to :back }
end
end
end
A bit verbose but I want to add more stuff.
I can add comments perfectly but I can't view validation errors.
I leave all blank (my model have validation stuff) and I see that the comment created in the create action have the errors and go to the else path.
But... The form doesn't show any errors.
I think that I have an object with the erorrs but when I redirect back, the object I pass to the form is a new one again and doesn't have the errors.
So, where is the problem?
EDIT: Extra stuff:
Im my show.html.erb I also have this (before the form):
<ol class="commentlist">
<%= render @post.comments %>
</ol>
So, When in the show action I put the extra variable:
def show
@post = Post.find(params[:id])
@comment = @post.comments.new
It seems that the render wants to render the empty comment too and make an exception.
How to bypass that?
Upvotes: 1
Views: 699
Reputation: 7434
When you redirect back, you are calling the PostsController#show
action again which will reset all of the instance variables. If you wanted to save state after the failed CommentsController#create
call, you would need to call render 'posts/show'
instead of redirect :back
which would reuse the instance variables which were declared in the current action
def create
# assuming you have nested the comments routes underneath posts...
@post = Post.find(params[:post_id])
@comment = @post.comments.build(params[:comment])
respond_to do |format|
if @comment.save
format.html { redirect_to :back }
else
format.html do
# remember to declare any instance variables that PostsController#show requires
# e.g. @post = ...
render 'posts/show'
end
end
end
end
You would also need to make sure that the partial uses @comment
instead of creating a new comment each time
<%= render :partial => 'comments/form', :locals => {:comment => @comment } %>
And make sure the PostsController
declares @comment
# e.g. inside PostsController
def show
@post = Post.find(params[:id])
@comment = Comment.new
end
The most important thing to remember is to make sure that the code inside the failed create
call initializes all the instance variables that the PostsController#show
action template requires otherwise you'll get errors.
Upvotes: 1