具有嵌套属性的错误复数错误消息

时间:2012-02-08 00:21:58

标签: ruby-on-rails-3.1 nested-attributes

使用Rails 3.1.3。我有帐户和用户。一个帐户可以拥有多个用户。我按照this answer中的说明使用accepts_nested_attributes_for进行了设置。

我有一个new.html.erb视图,可以同时接受一个帐户和一个用户的数据。 (用户的数据进入“子表单”。)表单工作正常。但是,如果存在错误,则子窗体的字段的消息是多元的,即使它们应该是单数的。例如,我得到

Users password doesn't match confirmation
Users password is too short (minimum is 8 characters)

而不是

User password doesn't match confirmation
User password is too short (minimum is 8 characters)

我不认为这是一个变形问题,因为“用户”遵循标准的复数规则。相反,它必须与在子窗体中使用嵌套属性有关。在我的例子中,子表单返回一个包含一个用户的数组,但理论上它可以为多个用户返回数据。

当仅引用数组中的一个元素时,如何/在何处可以告诉Rails不要复数?

<小时/> 修改3/14/2012以显示控制器和视图:

app / controllers / accounts_controller.rb (仅限“新建”操作):

class AccountsController < ApplicationController
  before_filter :authenticate_user!, :except => [:new, :create]
  before_filter :user_signed_out,    :only   => [:new, :create]
  load_and_authorize_resource # CanCan - does a standard load for each action, and authorizes user

  def new
    # CanCan:  @account = Account.new (and tests each attribute for ability)
    @account.users.build
    @title = "Sign Up for a New Account"
    @header = "Sign up for a new account"
  end
end

应用/视图/帐户/ new.html.erb

<h2><%= @header %></h2>

<%= form_for(@account) do |f| %>
  <%= render 'account_fields', :f => f %>

  <%= f.fields_for :users do |user_form| %>
    <div class="field"><%= user_form.label :email %><br />
    <%= user_form.email_field :email %></div>
    <div class="field"><%= user_form.label :password %><br />
    <%= user_form.password_field :password %></div>
    <div class="field"><%= user_form.label :password_confirmation %><br />
    <%= user_form.password_field :password_confirmation %></div>
  <% end %>

  <div class="actions">
    <%= f.submit "Create Account" %>
  </div>
<% end %>

我在上面error_messages_for区块内尝试了f.fields_for

在所有观看之前由布局呈现的

app / views / shared / _error_messages.html.erb

<% if object.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(object.errors.count, "error") %> 
      prohibited this <%= object.class.to_s.underscore.humanize.downcase %>
      from being saved:</h2>
    <p>There were problems with the following fields:</p>
    <ul>
    <% object.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

2 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为它是一个has_many关联。您可以做的是覆盖渲染的对象名称,如下所示:

<%= error_messages_for @account, :object => [@account, :users], :object_name => 'Account' %>

这允许您将该标签更改为您想要的任何内容,例如:

<%= error_messages_for @account, :object => [@account, :users], :object_name => 'Profile' %>

然后看起来像

Profile password doesn't match confirmation
Profile password is too short (minimum is 8 characters)

享受!

答案 1 :(得分:0)

正如@Marc建议的那样,消息是根据模型生成的。当涉及accepts_nested_attributes_for时,这会变得棘手,因为它在我的帐户模型中:

has_many :users, :inverse_of => :account, :dependent => :destroy
accepts_nested_attributes_for :users

为了更深入地了解错误对象,我将<%= object.errors.inspect %>插入 _error_messages.html.erb 。这向我展示了完整的错误对象,例如:

  

#&lt; ActiveModel :: Errors:0xb5c86a8 @base =#&lt; Account id:nil,name:“”,created_at:nil,updated_at:nil&gt;,   @messages = {:“users.password”=&gt; [“与确认不符”,“也是   短(最少8个字符)“],:name =&gt; [”不能为空白“]}&gt;

当Rails生成full_messages数组时,它只会将每个属性和消息提供给full_message方法。例如,如果属性是“users.password”,那么它将只是“人性化”(不考虑数组中的对象数)并与消息连接以返回

  

用户密码与确认不符   用户密码太短(最少8个字符)

任何解决方案的关键是避免使用full_messages:

  • 虽然我无法让error_messages_for工作,但也不会 很难写一个允许指定自定义对象的小助手 名称预先添加到消息中。

  • 通过突出显示来完全避免显示对象名称的问题 错误的特定字段,然后放置错误消息后缀 到了现场。这适用于Twitter Bootstrap和SimpleForm。

  • This article为提供明确提供了一个很好的理由 每条消息的翻译,声称任何尝试 连接字符串必然会导致问题。