2010-04-22 69 views
0

任何人都可以解釋爲什麼會發生這種情況?Ruby on Rails奇怪的行爲與ActiveRecord錯誤處理

mybox:$ ruby script/console 
Loading development environment (Rails 2.3.5) 
>> foo = Foo.new 
=> #<Foo id: nil, customer_id: nil, created_at: nil, updated_at: nil> 
>> bar = Bar.new 
=> #<Bar id: nil, bundle_id: nil, alias: nil, real: nil, active: true, list_type: 0, body_record_active: false, created_at: nil, updated_at: nil> 
>> bar.save 
=> false 
>> bar.errors.each_full { |msg| puts msg } 
Real can't be blank 
Real You must supply a valid email 
=> ["Real can't be blank", "Real You must supply a valid email"] 

到目前爲止,這是完美的,這就是我想要的錯誤消息閱讀。現在更多:

>> foo.bars << bar 
=> [#<Bar id: nil, bundle_id: nil, alias: nil, real: nil, active: true, list_type: 0, body_record_active: false, created_at: nil, updated_at: nil>] 
>> foo.save 
=> false 
>> foo.errors.to_xml 
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<errors>\n <error>Bars is invalid</error>\n</errors>\n" 

這是我無法弄清楚。爲什麼我得到酒吧是無效的與上面顯示的錯誤信息,[「真實不能空白」,「真實的你必須提供一個有效的電子郵件」]等

我的控制器只是有一個respond_to方法與以下其中:

format.xml { render :xml => @foo.errors, :status => :unprocessable_entity } 

我該如何獲得這個輸出真正的錯誤信息,以便用戶瞭解他們做錯了什麼?如何在我的控制器中編寫我的渲染方法以顯示所有適當的錯誤消息?

回答

0

這是因爲bar的錯誤存儲在bar對象中。爲了得到這些錯誤,你必須做這樣的事情:

foo.bar.each do |bar| 
    bar.errors.each_full { |msg| puts msg } 
end 

這一切都令人費解給我,但我還沒有想出要得到一個列表中的所有錯誤的最好方法(除了處理它我的自我) 。我理解它背後的推理(因爲每個對象應該只知道它自己的錯誤)。我通常所做的是擴展ActiveRecord::Errors並創建一個新的each_full_with_associations函數,將它們全部返回。

當你在帶嵌套字段的表單上看到它時,這一切都很有意義。在這種情況下,錯誤顯示正確,一切都很好。

+0

我需要編寫一個xml構建器模板來顯示這些錯誤消息嗎? – randombits 2010-04-22 01:18:49

+0

查看我的編輯... – 2010-04-22 01:23:10

+0

有機會看到我如何去做這個事情的例子嗎?希望能夠在我的xml輸出中顯示所有子錯誤。 – randombits 2010-04-22 01:25:42

1

我認爲你正在使用

validates_associated:酒吧在foo.rb MODEL

所以只給予「酒吧是無效的」

檢查錯誤消息吧要麼就得在

VIEW做以下

<%= error_messages_for :foo, :bar %> 

控制器

foo.bar.errors.to_xml

&跳過「欄是無效」消息把以下的方法在foo.rb

def after_validation 
    # Skip errors that won't be useful to the end user 
    filtered_errors = self.errors.reject{ |err| %w{ bar }.include?(err.first) } 
    self.errors.clear 
    filtered_errors.each { |err| self.errors.add(*err) } 
    end 
+0

我不認爲error_messages_for適用於xml構建器模板。 – randombits 2010-04-23 00:41:05

0

我們用來重寫在特定模型的方法errors ,如果我們還需要兒童對象的錯誤,那麼這樣的行爲可以使用

class Foo < ActiveRecord::Base 

    alias :errors_without_children :errors 

    def errors 
    self.bars.each do |i| 
     i.errors.each_full do |msg| 
     errors_without_children.add_to_base msg 
     end 
    end 
    errors_without_children 
    end 

end 

您仍然可以優化它。但是這個已經將所有的條形對象的錯誤信息添加到foo中。