如何使用事务以多模型forms显示错误消息?

组织和用户这两个模型具有1:多的关系。 我有一个组合注册表单,组织和该组织的用户都可以注册。

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

我应该如何调整下面的代码,以便显示用户的错误消息?

def new @organization = Organization.new @user = @organization.users.build end def create @organization = Organization.new(new_params.except(:users_attributes)) #Validations require the organization to be saved before user, since user requires an organization_id. That's why users_attributs are above excluded and why below it's managed in a transaction that rollbacks if either organization or user is invalid. This works as desired. @organization.transaction do if @organization.valid? @organization.save begin # I executed next line in debugger (with invalid user info), which correctly responds with: ActiveRecord::RecordInvalid Exception: Validation failed: Email can't be blank, Email is invalid, Username can't be blank, etc. @organization.users.create!(users_attributes) rescue # Should I perhaps add some line here that adds the users errors to the memory? raise ActiveRecord::Rollback end end end if @organization.persisted? flash[:success] = "Yeah!" redirect_to root_url else @user = @organization.users.build(users_attributes) # Otherwise the filled in information for user is gone (fields for user are then empty) render :new end end 

表单视图包括:

    # Other fields   # Other fields    

错误消息部分如下:

  
  • 更新:按照Rob的回答,我到达了下面的错误部分。 这仍然不会显示用户的错误消息。 我在下面的代码中添加了调试器响应,出于某种原因nested_model.errors.any? 返回false,而控制器内的调试器(见上文)确实为用户返回错误消息。

      
    The form contains .
    # Debugger: responds with "local-variable" for "defined?(nested_models)" and for "nested_models.any?" returns true.
      # 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. #Initially had "unless nested_model.valid?" but then errors for User are immediately displayed on loading the form page (new method).

    尝试添加validates_associated :users您在组织中的has_many :users关联下的has_many :users

    http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_associated

    您是否在救援区成功编写了代码?

      rescue ActiveRecord::RecordInvalid => exception # do something with exception here raise ActiveRecord::Rollback @organization.users.build if @organization.users.blank? render :new and return 

    此代码看起来会创建一个新的空用户,无论validation不正确。 假设组织没有用户,则渲染new将简单地返回没有错误,因为用户已成功创建。

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

    组织has_many:用户和用户belongs_to:组织

    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 %> 

    在控制器中

     def create @organization = Organization.new(new_params) if @organization.save flash[:success] = "Yeah!" redirect_to root_url else render :new end end 

    这与这个问题非常相关。 关键是<%= render 'shared/error_messages', object: f.object %> ,我认为,它只是在传递的对象上调用.errors方法(在本例中为organization )。

    但是,由于user错误与user对象一起存在,因此不会返回它们,因此不会显示它们。 这需要简单地更改视图逻辑以在各种user模型上显示.errors的结果。 你想怎么做取决于你。 在链接的线程中,接受的答案有错误消息显示代码内联而不是部分,所以你可以这样做,但它会有点多余。

    我会修改我的shared/error_messages.html.erb文件以检查另一个被称为nested_models传递本地。 然后它将使用它来搜索关联的模型并在其上包含错误。 我们只需要检查它是否首先被定义,以便您的其他视图没有嵌套模型不会导致它引发错误。

    共享/ error_messages.html.erb

     <% if object.errors.any? %> 
    Object Errors:
      <% object.errors.full_messages.each do |msg| %>
    • <%= msg %>
    • <% end %>
    <% if defined?(nested_models) && nested_models.any? %> Nested Model(s) Errors:
      <% nested_models.each do |nested_model| %> <% unless nested_model.valid? %>
      • <% nested_model.errors.full_messages.each do |msg| %>
      • <%= msg %>
      • <% end %>
    • <% end %> <% end %>
    <% end %>
    <% end %>

    然后你只需要在视图中更改一行:

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

    看起来你的控制器中有很多不可测试的逻辑。 看起来对你来说逻辑会更好地使用简单的FormObject模式。 https://robots.thoughtbot.com/activemodel-form-objects