I have a datamapper model that has a unique index on a property called name. I want to create new records when a name doesn't already exist and silently ignore attempts to create records with duplicate names. What's the "right" way to do this in datamapper?
One solution I came up with is simply to ignore the exception:
begin
Committer.create!(:name => committer)
rescue DataObjects::IntegrityError => e # ignore duplicate inserts
end
If you have a better (more idiomatic) way of doing it, please let me know.
The best approach is to use the dm-validations gem, and ensure that your name property is specified as being unique, eg:
class Committer
include DataMapper::Resource
# ... other properties ...
property :name, String, :length => 1..100, :required => true, :unique => true
end
The dm-validations gem will introspect your model and automatically setup validations for your properties. In this case it won't allow more than one Committer to have the same name.
Here is another solution I came up with:
require 'dm-core'
require 'dm-validations'
require 'dm-more'
record = Committer.find_or_create(:name => committer)
If you're using this in sinatra, requiring dm-more seems to cause other problems. My solution was to require my own file that only contained the following code:
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
I think the best answer is to use first_or_create, which as Dan points out above, is already built into datamapper and therefore doesn't need to be declared.
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)