2010-02-25 54 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