Project

is_unique

0.0
Repository is archived
No commit activity in last 3 years
No release in over 3 years
Makes ActiveRecord return existing records instead of creating duplicates
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

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