2010-02-25 44 views
1

我有一个datamapper模型,它在名为property的属性上具有唯一索引。我想在名称尚不存在时创建新记录,并默默地忽略尝试创建具有重复名称的记录。在datamapper中做这件事的“正确”方法是什么?我想出了如何忽略使用数据映射器的重复插入

回答

1

我认为最好的答案是first_or_create使用,这成丹上面所指出的,已建成的DataMapper,因此不需要申报。

require 'dm-core' 
require 'dm-validations' 

class Committer 
    include DataMapper::Resource 
    property :id, Serial 
    property :name, String, :unique_index => true 
    validates_present :name 
    validates_is_unique :name 
end 
committer = "George" 
record = Committer.first_or_create(:name => committer) 
0

一种解决方案是简单地忽略异常:

begin 
    Committer.create!(:name => committer) 
    rescue DataObjects::IntegrityError => e # ignore duplicate inserts 
    end 

如果你有这样做的更好(更地道)的方式,请让我知道。

1

最好的方法是使用DM-验证的宝石,并确保指定的name属性作为唯一的,例如:

class Committer 
    include DataMapper::Resource 

    # ... other properties ... 

    property :name, String, :length => 1..100, :required => true, :unique => true 
end 

的DM-验证创业板将反思你的模型,并自动设置验证为您的物业。在这种情况下,它不允许多个提交者具有相同的名称。

+0

谢谢丹。我主要关心的不是如何执行唯一性,而是如何执行INSERT IGNORE - 即如何创建新记录,但是如果重复记录已经存在,将自动失败。我想知道做这件事的最好方法是什么。 – cayblood 2010-02-26 06:09:13

+0

不能在没有插件的情况下在DataMapper中执行INSERT IGNORE,但是没有一个可以执行此atm。 – dkubb 2010-02-26 18:57:36

+0

只是为了澄清,我并不是故意特意要求使用INSERT IGNORE。任何完成我目标的事情都很好。 – cayblood 2010-02-27 21:11:04

0

这里是另一个解决方案,我想出了:

require 'dm-core' 
require 'dm-validations' 
require 'dm-more' 
record = Committer.find_or_create(:name => committer) 

如果你在西纳特拉用这个,需要DM-更多的似乎会导致其他 问题。我的解决办法是要求我自己的文件,只有 包含以下代码:

module DataMapper 
module Model 
    def first_or_create(conditions = {}, attributes = {}) 
    first(conditions) || create(conditions.merge(attributes)) 
    end 

    alias find_or_create first_or_create 
end 
end 
+0

'Model#first_or_create'方法已经是DataMapper的一部分。另外,我通常不推荐使用名为'#find_ *'的查找器,因为它们可能与其他插件(如dm-ar-finders)相冲突;但更重要的是返回第一个东西的查找程序的DataMapper命名约定是使用'#first_ *'前缀。 – dkubb 2010-02-27 10:18:18

+0

好的,谢谢丹。 – cayblood 2010-02-27 21:11:46