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
locationsWHERE (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 (c) 2010 Loco2, released under the MIT license