Is Unique
This is a simple ActiveRecord extension that makes sure that no duplicate records are added to the database. When you create a new model instance that already exists, it won’t create a new record, but will return the existing one instead. The extension generates a hash off the model attributes and use it to check for existing records. Of course, it ignores primary key, created_at, updated_at and other columns that you ask it to.
Here’s an example. Say you have a Location model and you want all your locations to be unique. When you add a new location you’d like to check whether it already exists and if it does, you don’t want to create a new record.
$ ./script/generate model Location name:string lat:float lng:float alias:string
IsUnique will take care of that. You need to install the gem:
$ sudo gem install is_unique
Then you need to add a column to your table to store a unique hash that would be used to check for existing records. The gem includes a generator for that:
$ ./script/generate is_unique Location
In the model you need to specify that it’s supposed to be unique:
class Location < ActiveRecord::Base
is_unique
end
Then fire up the console and try it:
>> l = Location.create(:name => ‘London’, :lat => ‘51.5’, :lng => ‘-0.13’, :alias => ‘Londinium’)
Location Load (0.4ms) SELECT * FROM `locations` WHERE (`locations`.`unique_hash` = '...') LIMIT 1
Location Create (0.6ms) INSERT INTO "locations" ...
> #<Location id: …>
>> l.clone.save
Location Load (0.7ms) SELECT * FROM "locations" WHERE ("locations"."unique_hash" = '...') LIMIT 1
Location Load (0.6ms) SELECT * FROM "locations" WHERE ("locations"."id" = 1)
> true
Now there’s a couple of customization options. First, you can ignore certain attributes when calculating the hash. Say there may be different aliases for a location, but you still want just one record in the database. The is_unique method accepts an ignore parameter for that purpose:
class Location < ActiveRecord::Base
is_unique :ignore => :alias
end
>> l = Location.last
Location Load (0.7ms) SELECT * FROM "locations" ORDER BY locations.id DESC LIMIT 1
> #<Location …>
>> n = l.clone
> #<Location …>
>> n.alias = ‘Something different’
> “Something different”
>> n.save
Location Load (0.7ms) SELECT * FROM "locations" WHERE ("locations"."unique_hash" = '...') LIMIT 1
Location Load (0.6ms) SELECT * FROM "locations" WHERE ("locations"."id" = 2)
> true
>> n == l
> true
If you’d like to name the unique hash column differently (it’s “unique_hash” by default), you need to provide the name to the generator:
$ ./script/generate is_unique Location my_unique_hash_column_name
and specify it in the model:
class Location < ActiveRecord::Base
is_unique :hash_column => :my_unique_has_column_name
end
Copyright © 2010 Loco2, released under the MIT license