开发者

How do I display error messages for nested resource validations?

I'm creating a basic blog application and I'm running into issues displaying error messages when a user tries to submit a blank comment. Instead of getting a nice looking error message, an active record error message with the correct validation erorrs. Such as

ActiveRecord::RecordInvalid in CommentsController#create

Validation failed: Name can't be blank, Email can't be blank

In my article/show view I have the following code:

<%= form_for([@article, @article.comments.build]) do |f| %>
  <%= render "shared/error_messages", :target => @article %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <p><%= f.submit %></p>
<% end %>

My error messages partial looks like this:

    <% if target.errors.any? %>
       <div id="error_explanation">
         <h2><%= pluralize(target.errors.count, "error") %> prohibited this record from                 being saved:</h2>

    <ul>
      <% target.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% 开发者_运维技巧end %>
    </ul>
  </div>
<% end %>

I know the answer is simple but I can't figure it out.

Create action in comments controller:

def create
@article = Article.find(params[:article_id])
@comment = @article.comments.build(params[:comment])
respond_to do |format|
  if @comment.save
    format.html { redirect_to(@article, :notice => 'Comment was successfully created.') }
    format.xml  { render :xml => @article, :status => :created, :location => @article }
  else
    format.html { render :action => "articles/show" }
    format.xml  { render :xml => @comment.errors, :status => :unprocessable_entity }
  end
end


I had a similar problem. everything seemed to work fine, but I was not getting any errors The solution i found is to build the comment in article#show instead of the view:

@article = Article.find(params[:id])
@comment = @article.comments.build(params[:comment])

and in your articles#show don't use @article.comments.build but @comment:

<%= form_for([@article, @comment]) do |f| %>
   <%= render 'shared/error_messages', :object => f.object %>
   <p><%= f.submit %></p>
<% end %>

make sure you build the comment in your comment#create as well (you really have no choice though :P)

also, I don't know if it matters (i'm pretty new to ruby), but I think you need to pass f.object instead of @comment.


I think you're saying that you get the big grey-on-white error page, right?

Check the backtrace, but I suspect that this is coming from the create action in the controller, not the view.

If your controller uses save! with the ! at the end, that means that it will raise an error if the record is invalid. save, on the other hand, returns true or false and lets you use simple branch logic to decide how to react.

If my hunch on save! isn't right, though, please post controller code so we can dig deeper :) Thanks!


The solution was to direct the comments created action back to the correct controller/action and target @comment in my error message partial.

Final view

    <%= form_for([@article, @article.comments.build]) do |f| %>
  <%= render "shared/error_messages", :target => @comment %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <p><%= f.submit %></p>
<% end %>

Final create action in comments controller

def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.build(params[:comment])
    respond_to do |format|
      if @comment.save
        format.html { redirect_to(@article, :notice => 'Comment was successfully created.') }
        format.xml  { render :xml => @article, :status => :created, :location => @article }
      else
        format.html { render :action => "articles/show" }
        format.xml  { render :xml => @comment.errors, :status => :unprocessable_entity }
      end
    end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜