【问题标题】:How to pass a model when redirecting to another action in order to display the model errors in the redirected view重定向到另一个操作时如何传递模型以便在重定向视图中显示模型错误
【发布时间】:2016-04-14 19:34:00
【问题描述】:

当无法通过comments#create 保留评论时,我想在articles\view.html.erb 上显示新@comment 的验证错误。

TLDR,我使用Getting Started 教程和rails 4.2.6 和ruby 2.2.3 创建了一个博客。


一个博客有很多文章,每篇文章都有很多评论

按照教程,发布新评论的表单位于articles\view.html.erb 中,并保留在comments#create 中。发布新评论后,它会再次重定向到articles#show

class Article < ActiveRecord::Base
  has_many :comments
  validates :title, presence: true, length: { minimum: 5 }
end

class Comment < ActiveRecord::Base
  belongs_to :article
end

我使用相同的视图 - articles/show.html.erb - 显示文章及其cmets并发布新评论

<p><strong>Title:</strong><%= @article.title %></
<p><strong>Text:</strong><%= @article.text %></p>

<h2>Comments</h2>
<% @article.comments.each do |comment| %>
  <p><strong>Commenter:</strong><%= comment.commenter %></p>
  <p><strong>Comment:</strong><%= comment.body %></p>
<% end %>

<h2>Add a comment:</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p><%= f.label :commenter %><br><%= f.text_field :commenter %></p>
  <p><%= f.label :body %><br><%= f.text_area :body %></p>
  <p><%= f.submit %></p>
<% end %>

<%= link_to 'Edit', edit_article_path(@article) %> |
<%= link_to 'Back', articles_path %>

通过articles_controller

def show
  @article = Article.find(params[:id])
end

comments_controller 发表新评论

def create
  @article = Article.find(params[:article_id])
  @comment = @article.comments.create(comment_params)
  redirect_to article_path(@article)
end

它按预期工作:)


这是我的问题开始的地方......

我决定进一步向 Comment 模型添加一些验证

class Comment < ActiveRecord::Base
  belongs_to :article   
  validates :commenter, presence: true
  validates :body, presence: true
end 

并在保存失败时显示注释错误。

首先,我尝试通过文章模型显示错误

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

然后我尝试在articles_controller 中使用全局变量@comment

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

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

它也没有用。

据我了解,这种方式不起作用,因为当我提交 新评论 时,我会重定向到文章显示操作 redirect_to article_path(@article) - 无论是成功还是不保存新评论评论 - 因此创建了一个新的评论实例,用它的错误覆盖前一个。

我最好的解决方案是使用带有错误消息的 flash 属性。看起来是这样的

comments_controller

def create
  @article = Article.find(params[:article_id])
  @comment = @article.comments.create(comments_params)
  redirect_to article_path(@article), flash: {new_article_errors: @comments.errors.full_messages}
end 

articles/show.html.erb

<% unless flash[:new_comment_errors].nil?  %>
  <div id="error_explanation">
    <h2>
      <%= pluralize(flash[:new_comment_errors].count, "error") %> prohibited this comment from begin saved:
    </h2>
    <ul>
      <% flash[:new_comment_errors].each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
  </div>
<% end %>

但这也不是最好的解决方案。它会显示错误但会丢失已填写的值(表格清晰)。

我需要通过redirect_to 传递@comment 吗? 像这样的

comments_controller

def create
  @article = Article.find(params[:article_id])
  @comment = @article.comments.build(comments_params)

  if @comment.save
    redirect_to article_path(@article)
  else 
    redirect_to article_path(:comment => params[:comment] )
  end
end

article_controller

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

  @comment.valid? if params[:comment]
end

现在我收到了No route matches 错误。我应该创建一个接收params[:comment] 的新操作吗?或编辑显示路线以接收它?

我已经阅读了Nested model validation - errors don't show,但没有帮助,因为他们建议在comments_controller 中创建新操作,而我不希望这样做(新帖子表单 需要在article/show.html.erb)。

Nested Model Form Part 1Nested Model Form Part 2 也没有帮助。

感谢您的宝贵时间和帮助!

【问题讨论】:

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

您可以渲染显示视图,而不是重定向到 ArticlesController#show 方法(您发现这会导致所有实例变量丢失)。

if @comment.save
  redirect_to article_path(@article)
else 
  render :template => 'articles/show'
end

您已经拥有 @template@comment 实例变量,因此它们将在渲染中使用。

【讨论】:

  • 我之前一直在寻找类似的东西,但没有找到。我会试试看。感谢您的时间@SteveTurczyn =b
  • 我输入了一个错字,现在已修复,所以如果它不起作用,请再次检查我的示例代码!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 2017-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多