Ruby on rails 如何解决Rails教程中关联模型的缺点

Ruby on rails 如何解决Rails教程中关联模型的缺点,ruby-on-rails,Ruby On Rails,我遵循了大多数情况下都很好的方法,但在涉及相关模型时缺乏一些细节(注释): 没有验证-添加它很容易,但是我不确定如何显示验证失败的错误消息 使用@article.comments.build可以有效地显示该会话中“创建”另一条评论的评论表单,因此,如果您遍历所有评论,就会有一条额外的空白评论。这只是巧合,指南在执行这行代码之前列出了注释,因此没有遇到问题 当我试着用1。(下面将详细介绍),我不知道如何解决2。-它可能属于它自己的问题,但我甚至不知道如何命名它 尝试验证/错误显示 我尝试基本上应用

我遵循了大多数情况下都很好的方法,但在涉及相关模型时缺乏一些细节(注释):

  • 没有验证-添加它很容易,但是我不确定如何显示验证失败的错误消息
  • 使用
    @article.comments.build
    可以有效地显示该会话中“创建”另一条评论的评论表单,因此,如果您遍历所有评论,就会有一条额外的空白评论。这只是巧合,指南在执行这行代码之前列出了注释,因此没有遇到问题
  • 当我试着用1。(下面将详细介绍),我不知道如何解决2。-它可能属于它自己的问题,但我甚至不知道如何命名它

    尝试验证/错误显示

    我尝试基本上应用相同的策略来显示文章中的错误消息,同样用于评论。我知道会有一些额外的复杂性,但我试图以逻辑的方式进行导航。这就是我所改变的:

    app/models/comments.rb

    class Comment < ApplicationRecord
      belongs_to :post
    
      validates :commenter, presence: true
      validates :body, presence: true
    end
    
    class注释
    app/controllers/comments\u controller.rb

    class CommentsController < ApplicationController
      def create 
        @article = Post.find(params[:article_id])
        @comment = @article.comments.new(comment_params)
    
        if @comment.save
          redirect_to article_path(@article)
        else
          render 'articles/show'
        end
      end
    
      def destroy
        ...
    
    class CommentsController
    app/views/comments/_form.html.erb

    <%= form_for([@article, @article.comments.build]) do |f| %>
      <% if self.instance_variable_defined?('@comment') and @comment.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@comment.errors.count, 'error') %> occurred:</h2>
          <ul>
            <% @comment.errors.full_messages.each do |msg| %>
              <li><%= msg %></li>
            <% end %>
          </ul>
        </div>
      <% end %>
    
      <p>
        <%= f.label :commenter, 'Your Name' %>
        ...
    
    
    发生:
    
    ...
    在成功显示错误消息的同时,出现了以下问题:

  • 因为它使用了render而不是redirect,用户最终得到的URL通常无法提供
    GET
    请求(即/posts/1/comments)-这很奇怪,因为如果页面再次加载,它将返回404。但我不能使用重定向,因为这样尝试创建的注释(带有错误消息)将丢失
  • 大概是因为在渲染之前执行了
    @article.comments.new
    ,这与第2部分中描述的问题相同。上面(关于
    @article.comments.build
    )出现:显示一条空白注释
  • 这就是我被困的地方。这些都是相当基本的问题——没有它们,系统就不完整,但我不知道正确的解决方案是什么


    如何在避免上述问题的同时显示这些错误?

    显示错误的解决方案是正确的。当您呈现
    articles/show
    而不是重定向时,正如您所想的那样,您最终会进入
    /posts/:id/comments
    ,因为这是刚刚调用的HTTP方法POST的当前路径

    要显示错误并重定向到新路径,您可以对代码进行一些更改:

    1) 在创建操作中:

    if @comment.save
      flash[:comment] = nil
      redirect_to article_path(@article)
    else
      flash[:comment] = @comment
      redirect_to article_path(@article)
    end
    
    2) 在show article操作中:

    @comment = flash[:comment] || @article.comments.build
    
    3) 在文章显示视图中,将
    行的
    表单_替换为:

    <%= form_for([@article, @comment]) do |f| %>
    
    
    
    然后您可以使用代码显示错误:

      <% if self.instance_variable_defined?('@comment') and @comment.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@comment.errors.count, 'error') %> occurred:</h2>
          <ul>
            <% @comment.errors.full_messages.each do |msg| %>
              <li><%= msg %></li>
            <% end %>
          </ul>
        </div>
      <% end %>
    
    
    发生:
    
    此解决方案还可以解决您遇到的第二个问题


    如果我误解了您的问题,请告诉我并帮助您。

    您显示错误的解决方案是正确的。当您呈现
    articles/show
    而不是重定向时,正如您所想的那样,您最终会进入
    /posts/:id/comments
    ,因为这是刚刚调用的HTTP方法POST的当前路径

    要显示错误并重定向到新路径,您可以对代码进行一些更改:

    1) 在创建操作中:

    if @comment.save
      flash[:comment] = nil
      redirect_to article_path(@article)
    else
      flash[:comment] = @comment
      redirect_to article_path(@article)
    end
    
    2) 在show article操作中:

    @comment = flash[:comment] || @article.comments.build
    
    3) 在文章显示视图中,将
    行的
    表单_替换为:

    <%= form_for([@article, @comment]) do |f| %>
    
    
    
    然后您可以使用代码显示错误:

      <% if self.instance_variable_defined?('@comment') and @comment.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@comment.errors.count, 'error') %> occurred:</h2>
          <ul>
            <% @comment.errors.full_messages.each do |msg| %>
              <li><%= msg %></li>
            <% end %>
          </ul>
        </div>
      <% end %>
    
    
    发生:
    
    此解决方案还可以解决您遇到的第二个问题


    如果我误解了你的问题,请让我知道并帮助你。

    受@evedovelli使用
    flash
    的启发,但解决了它所遇到的问题(如该答案的评论中所述),我最终使用了:

    • flash[:comment\u errors]=@comment.errors.full\u messages
      在重定向中传递错误消息本身。我无法刷新
      @comment
      @comment.errors
      ,因为它们以散列形式结束,而不是原始对象的实例,因此失去了有用的方法,而
      完整消息
      只是一个数组,因此被完整地传递
    • form_for([@post,Comment.new])do | f |
      (与
      @post.comments.new/build
      相反)。该新注释不会立即链接到
      @post
      ,因此不会出现在
      @post.comments.all
      中。不过,该表单仍然有效——提交的内容将仅在该帖子下创建评论。然而,我觉得这仍然是在避免真正的问题:如果我出于某种原因尝试循环浏览所有评论,那么新的、未保存的评论将再次被找到
    在为
    部分编写
    表格后:

    然后会再次找到新的、未保存的注释

    我意识到我偶然发现了一些潜在的搜索词(我以前找不到解决这个问题的词)!所以我搜索了
    rails collection get save only
    ,这导致