Ruby on rails 如何在具有事务的多模型表单中显示错误消息?

Ruby on rails 如何在具有事务的多模型表单中显示错误消息?,ruby-on-rails,ruby,ruby-on-rails-4,activerecord,transactions,Ruby On Rails,Ruby,Ruby On Rails 4,Activerecord,Transactions,组织和用户这两个模型具有1:many关系。我有一个联合注册表单,其中一个组织加上该组织的一个用户可以注册 我遇到的问题是:当为用户提交无效信息时,它会再次呈现表单,但不会显示用户的错误消息(例如“用户名不能为空”)。当提交有效信息时,该表单确实可以工作,并且它确实为组织显示错误消息,只是不为用户显示 <% if object.errors.any? %> <div id="error_explanation"> <div class="alert ale

组织和用户这两个模型具有1:many关系。我有一个联合注册表单,其中一个组织加上该组织的一个用户可以注册

我遇到的问题是:当为用户提交无效信息时,它会再次呈现表单,但不会显示用户的错误消息(例如“用户名不能为空”)。当提交有效信息时,该表单确实可以工作,并且它确实为组织显示错误消息,只是不为用户显示

<% if object.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-danger">
      The form contains <%= pluralize(object.errors.count, "error") %>.
    </div>

    <ul>
      <% object.errors.full_messages.each do |msg| %>
        <li><%= msg.html_safe %></li>
      <% end %>
    </ul>

  </div>
<% end %>

<% if defined?(nested_models) && nested_models.any? %>
  # Debugger: responds with "local-variable" for "defined?(nested_models)" and for "nested_models.any?" returns true.
  <div id="error_explanation">
    <ul>
      <% nested_models.each do |nested_model| %>
      # Debugger: "nested_model" has the same values as "nested_models.any?", as you would expect. But for "nested_model.errors.any?" it returns false, which it shouldn't.
        <% if nested_model.errors.any? %>    #Initially had "unless nested_model.valid?" but then errors for User are immediately displayed on loading the form page (new method).
          <ul>
            <% nested_model.errors.full_messages.each do |msg| %>
              <li><%= msg.html_safe %></li>
            <% end %>
          </ul>
        <% end %>
      <% end %>
    </ul>
  </div>
<% end %>
我应该如何调整下面的代码,以便同时显示用户的错误消息

表单视图包括:

<%= form_for @organization, url: next_url do |f| %>
    <%= render partial: 'shared/error_messages', locals: { object: f.object, nested_models: f.object.users } %>
    <%= f.text_field :name %>
        # Other fields

    <%= f.fields_for :users do |p| %>
        <%= p.email_field :email %>
            # Other fields
    <% end %>

    <%= f.submit "Submit" %>
<% end %>

尝试在组织中的
has\u many:users
关联下添加
验证\u associated:users


尝试在组织中的
具有多个:用户的关联下添加
验证关联的:用户


在救援封锁期间,您是否成功地编写代码创建了人员

  rescue ActiveRecord::RecordInvalid => exception
      # do something with exception here
      raise ActiveRecord::Rollback
      @organization.users.build if @organization.users.blank?
      render :new and return
这段代码看起来会创建一个新的空用户,不管验证是否错误。如果组织没有用户,则render new将不会返回任何错误,因为用户已成功创建


这种方法的控制流程有一些结果,肯定需要进一步细分。我会使用byebug,然后用一个不正确的组织,然后是一个不正确的名称来遍历这个块。然后是一个用户属性不正确的空组织。

在救援封锁期间,您是否成功地编写了代码创建了人员

  rescue ActiveRecord::RecordInvalid => exception
      # do something with exception here
      raise ActiveRecord::Rollback
      @organization.users.build if @organization.users.blank?
      render :new and return
这段代码看起来会创建一个新的空用户,不管验证是否错误。如果组织没有用户,则render new将不会返回任何错误,因为用户已成功创建


这种方法的控制流程有一些结果,肯定需要进一步细分。我会使用byebug,然后用一个不正确的组织,然后是一个不正确的名称来遍历这个块。然后是一个用户属性不正确的空组织。

组织有多个:用户,用户属于:组织

organization.rb

accepts_nested_attributes_for :users
new.html.erb

<%= form_for @organization, url: next_url do |f| %>
 <%= render 'shared/error_messages', object: @organization %>
 <%= f.text_field :name %>
    # Other fields
 <%= f.fields_for(:users,@organization.users.build) do |p| %>
   <%= p.email_field :email %>
   # Other fields
 <% end %>
 <%= f.submit "Submit" %>
<% end %>

组织有多个:用户,用户属于:组织

organization.rb

accepts_nested_attributes_for :users
new.html.erb

<%= form_for @organization, url: next_url do |f| %>
 <%= render 'shared/error_messages', object: @organization %>
 <%= f.text_field :name %>
    # Other fields
 <%= f.fields_for(:users,@organization.users.build) do |p| %>
   <%= p.email_field :email %>
   # Other fields
 <% end %>
 <%= f.submit "Submit" %>
<% end %>
这是非常相关的。关键是,
是,我假定,只调用它所传递的对象上的
.errors
方法(在本例中,
组织

但是,由于
用户
错误驻留在
用户
对象中,因此不会返回错误,因此不会显示错误。这只需要简单地更改视图逻辑,就可以在各种
用户
模型上显示
错误
的结果。你想怎么做取决于你自己。在链接线程中,接受的答案将错误消息显示代码内联显示,而不是部分显示,因此您可以这样做,但这有点多余

我会修改我的
shared/error\u messages.html.erb
文件,以检查是否有另一个传递的本地文件,该文件名为
nested\u models
。然后,它将使用它来搜索相关的模型,并包含其中的错误。我们只需要先检查是否定义了它,这样其他没有嵌套模型的视图就不会引起错误

共享/错误消息.html.erb

<% if object.errors.any? %>
  <div class="error-messages">
    Object Errors:
    <ul>
      <% object.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
    <% if defined?(nested_models) && nested_models.any? %>
      Nested Model(s) Errors:
      <ul>
        <% nested_models.each do |nested_model| %>
          <% unless nested_model.valid? %>
            <li>
              <ul>
                <% nested_model.errors.full_messages.each do |msg| %>
                  <li><%= msg %></li>
                <% end %>
              </ul>
            </li>
          <% end %>
        <% end %>
      </ul>
    <% end %>
  </div>
<% end %>

对象错误:
嵌套模型错误:
然后您只需要更改视图中的一行:

<%= render partial: 'shared/error_messages', locals: { object: @organization, nested_models: @organization.users } %>

这与。关键是,
是,我假定,只调用它所传递的对象上的
.errors
方法(在本例中,
组织

但是,由于
用户
错误驻留在
用户
对象中,因此不会返回错误,因此不会显示错误。这只需要简单地更改视图逻辑,就可以在各种
用户
模型上显示
错误
的结果。你想怎么做取决于你自己。在链接线程中,接受的答案将错误消息显示代码内联显示,而不是部分显示,因此您可以这样做,但这有点多余

我会修改我的
shared/error\u messages.html.erb
文件,以检查是否有另一个传递的本地文件,该文件名为
nested\u models
。然后,它将使用它来搜索相关的模型,并包含其中的错误。我们只需要先检查是否定义了它,这样其他没有嵌套模型的视图就不会引起错误

共享/错误消息.html.erb

<% if object.errors.any? %>
  <div class="error-messages">
    Object Errors:
    <ul>
      <% object.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
    <% if defined?(nested_models) && nested_models.any? %>
      Nested Model(s) Errors:
      <ul>
        <% nested_models.each do |nested_model| %>
          <% unless nested_model.valid? %>
            <li>
              <ul>
                <% nested_model.errors.full_messages.each do |msg| %>
                  <li><%= msg %></li>
                <% end %>
              </ul>
            </li>
          <% end %>
        <% end %>
      </ul>
    <% end %>
  </div>
<% end %>

对象错误:
嵌套模型错误:
然后您只需要更改视图中的一行:

<%= render partial: 'shared/error_messages', locals: { object: @organization, nested_models: @organization.users } %>

看起来控制器中有很多不稳定的逻辑。看起来对于您来说,使用简单的FormObject模式逻辑会更好。
看起来控制器中有很多不稳定的逻辑。看起来对于您来说,使用简单的FormObject模式逻辑会更好。

恐怕还是一样,没有关于无效用户信息的错误消息。不过有一个区别:注册表单存在于
url/signup/organization
上。当它使用
new
呈现无效信息时,url将更改为
url/orga