2012-02-08 48 views
2

使用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顯示控制器和視圖:

應用程序/控制器/ 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 

應用/views/accounts/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 %> 

我在上面的f.fields_for區塊內嘗試error_messages_for

應用程序/視圖/共享/ _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 %> 

回答

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。這讓我明白了完整的錯誤對象,例如:

# < ::加載ActiveModel錯誤:0xb5c86a8 @基地=#<帳戶ID:無,名稱: 「」,created_at:無,的updated_at:無> , @messages = {:「users.password」=> [「與確認不符」,「也是 短(最小8個字符)」],::名稱=> [「不能爲空」] }>

當Rails生成full_messages數組時,它只是將每個屬性和消息提供給full_message方法。例如,如果該屬性是「users.password」,那麼將簡單地「人性化」(不考慮陣列中的對象的數量)並與消息連接以返回

用戶密碼不匹配確認
用戶密碼太短(最小爲8個字符)

任何解決方案的關鍵是要避免使用full_messages:

  • 雖然我不能得到error_messages_for的工作,它不會太 很難寫一個小幫手,允許指定一個自定義對象名稱以預先給消息。

  • 通過突出顯示錯誤的 特定字段並將錯誤消息後綴 添加到字段,避免顯示對象名稱的問題。這很適合Twitter Bootstrap和SimpleForm。

  • This article使一個很好的案例提供明確 翻譯每個消息,聲稱任何企圖 連接字符串,勢必會造成問題。

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) 

享受!

+0

有趣的想法,但似乎f.error_messages已從Rails 3中刪除,所以我無法測試它。我已經添加了SimpleForm和Twitter Bootstrap,它在包含錯誤的表單字段周圍放置一個高亮框,並僅添加錯誤文本的後綴。即這是一種解決方法,通過不實際命名對象來避免該問題。 – 2012-03-13 21:39:00

+0

不用它仍然可用。 'f.'是傳入你的'form_for'的變量。試試我上面的編輯。 – Marc 2012-03-14 02:35:18

+0

好吧,我恢復了我的代碼,以確保我可以複製該問題。然後,我爲該子表格添加了<%= error_messages_for @user,:object_name =>'User'%>',併爲#<#:0xa278328>獲得了未定義方法'error_messages_for'。這似乎證實了我在幾篇文章中看到的內容,例如[在Rails 3中沒有更多的error_messages_](http://www.suffix.be/blog/error-messages-for-rails3)。即使它工作了,我也不想把它改成「Profile」,我只是想讓它做正確的複數化:如果數組中只有一個用戶,不要複數化爲「users」。 – 2012-03-14 19:26:44