刚刚开始研究DataMapper for Ruby ORM我遇到了一个令我困惑的问题。
在我理解的情况下,在DataMapper中保存实例(通过 DataMapper :: Resource.save )时的默认行为是静默失败,从save方法返回false并收集任何错误错误集合。到目前为止,这很好,这可以按预期工作。我看到的问题是使用自然主键,设置重复的键会抛出异常,而不是从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
第一次保存,如果实例失败了:description属性的验证规则,则表现如预期。然而,具有重复键的实例的第三个保存没有,因为它引发了一个execption而不是很好地返回false。
这是为什么?显然可以解决,但感觉不太清楚。是否静默行为仅适用于DataMapper层中的验证错误,而基础数据存储区中的任何硬错误都将作为异常传播给调用者?
谢谢!
答案 0 :(得分:2)
正如另一位用户在评论中指出的那样,这是因为将raise_on_save_failure
设置为false
并不意味着不会发生例外情况。发生验证错误时,它始终会返回false
(没有例外)。
正如您所注意到的,数据库错误将以异常的形式爆炸。这些错误可能由于大量因素(连接失败,没有磁盘空间)而发生,包括像复制密钥这样的普通因素。 DataMapper无法知道您尝试保存的对象是否拥有重复键,因此它只是验证它并发送到实际发生错误的数据库。