2012-02-08 31 views
1

剛剛開始看的DataMapper Ruby的ORM我碰到的,混淆我沒有盡頭的一個問題。古怪的行爲在紅寶石DataMapper的節能實例時

保存DataMapper實例時的默認行爲(通過DataMapper :: Resource.save)據我所知,會以靜默方式失敗,從save方法返回false並收集錯誤集合中的任何錯誤。迄今爲止,這很好,這是按預期工作的。我看到的問題是與自然的主鍵,在這裏設置重複者將拋出一個異常,而不是默默地從保存方法返回,公然無視raise_on_save_failure的當前設置。考慮下面的片段;

require 'data_mapper' 

class Thing 
    include DataMapper::Resource 
    property :name , String, :key=> true 
    property :description, String, length: 2..5 
end 

DataMapper.setup :default, "sqlite:memory" 
DataMapper.finalize 
DataMapper.auto_migrate! 

#Create a thing and have it properly silently fail saving 
t1=Thing.new(:name=>"n1",:description=>"verylongdescription") 

t1.save #ok 
puts("t1 is saved:"+t1.saved?.to_s) 
t1.errors.each do |e| 
    puts e 
end 

#Create two things with the same key, and fail miserably in silently failing the second  save... 
t1=Thing.new(:name=>"n1",:description=>"ok") 
t2=Thing.new(:name=>"n1",:description=>"ok") 

t1.save #ok 
t2.save #not ok, raises Exception event though it shouldn't? 

puts("t2 is saved:"+t1.saved?.to_s) 
t2.errors.each do |e| 
    puts e 
end 

首先保存在一個實例失敗的驗證規則:描述財產的行爲與預期。第三個保存具有重複鍵的實例,但是不會,因爲它會引發一個執行,而不是很好地返回false。

這是爲什麼?顯然可以解決,但它並不是很清楚。那是無聲的行爲將僅適用於驗證錯誤在DataMapper的層的情況下,從底層數據存儲的任何硬錯誤將被傳播作爲例外來電?

謝謝!

+0

驗證捕獲最終用戶錯誤,重複鍵到數據庫是程序員錯誤。如果除以零或'save'序列中沒有處理'nil'正常,你會得到同樣的原因異常。 – 2012-02-08 20:10:24

+0

是的,這是有區別的,現在我在DataMapper中更多地瞭解驗證和靜默/非靜默行爲的目的。然後我猜測在上面的例子中,如果你添加了一個獨特的驗證, – osmbergs 2012-02-09 19:17:10

+0

不幸的是,唯一性驗證是不夠的,因爲它受到競爭條件的限制,所以您在數據庫中也需要一個唯一的約束條件,但是當競爭條件發生時您會得到一個異常。 – 2012-02-09 21:36:52

回答

2

正如另一位用戶在評論中指出的,這是因爲將raise_on_save_failure設置爲false並不意味着不會發生任何異常。發生驗證錯誤時,它將始終返回false(無一例外)。

數據庫錯誤將炸燬,因爲你注意到沒有,在出現異常的形式。這樣的錯誤可能發生由於大量的因素(連接失敗,沒有磁盤空間),包括平凡的像一個重複鍵。 DataMapper無法知道您要保存的對象是否擁有重複密鑰,因此它只是驗證它併發送到數據庫,實際發生錯誤的地方。