Created
May 20, 2009 15:48
-
-
Save thillerson/114891 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'uuidtools' | |
module UUIDasID | |
# | |
# When included, e.g. <code>include UUIDasID</code>, | |
# this method will be called, passing the class in | |
# | |
def self.included mod | |
# this will set up generate_uuid as a before_create callback | |
mod.instance_eval( %q{before_create :generate_uuid} ) | |
# here we define the macro method, has_uuid, and a query method, has_uuid? | |
mod.class_eval do | |
def self.has_uuid column_name, options={} | |
@has_uuid = true | |
@uuid_options = options.merge(:id => column_name) | |
end | |
def self.has_uuid? | |
@has_uuid || false | |
end | |
end | |
end | |
# | |
# This method is called whenever an ActiveRecord is created | |
# but should fail early if has_uuid wasn't called as a macro | |
# e.g. <code>has_uuid :guid, :unique_with => [:attr1, attr2]</code> | |
# | |
def generate_uuid | |
# fail early and quietly if this AR doesn't have a UUID | |
return true unless self.class.has_uuid? | |
options = self.class.instance_variable_get :@uuid_options | |
# this could help with testing | |
return true unless send("#{options[:id]}").nil? | |
# get each attribute that makes this record unique and make an array of string values | |
unique_attributes = options[:unique_with].inject([Time.new.to_s]) do |atts, current_att_name| | |
atts << send("#{current_att_name}").to_s | |
end rescue ['nuffin'] # or just make a dummy string array | |
# set the id to a SHA1 of the timestamp plus unique values (minus the dashes) | |
uuid = UUID.sha1_create(UUID_DNS_NAMESPACE, unique_attributes.join('')).to_s.gsub(/-/, '') | |
send("#{options[:id]}=", uuid) | |
# if the callback method uuid_generated exists, call it with the new uuid | |
uuid_generated(send("#{options[:id]}")) if respond_to?(:uuid_generated) | |
true | |
end | |
end | |
# | |
# Go on and put this feller on all ActiveRecords, at least once it's required | |
# maybe it will be a plugin someday | |
# | |
class ActiveRecord::Base | |
include UUIDasID | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment