Skip to content

Commit

Permalink
Added the rest of the files
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Morearty committed Jan 3, 2009
1 parent 54ef8f0 commit 2dc1e95
Show file tree
Hide file tree
Showing 5 changed files with 719 additions and 0 deletions.
34 changes: 34 additions & 0 deletions init.rb
@@ -0,0 +1,34 @@
# Copyright (c) 2005 Assembla, Inc.
# Portions Copyright (c) 2008 Intuit
#
# This plugin for ActiveRecord makes the "ID" field into a URL-safe GUID
# It is a mashup by Andy Singleton <andy@assembla.com> that includes
# * the UUID class from Bob Aman.
# * the plugin skeleton from Demetrius Nunes
# * the 22 character URL-safe format from Andy Singleton
# You can get standard 36 char UUID formats instead
# TODO: Auto-detect a character ID field and use a GUID in this case (DRY principle)
#
# It has been extended by Brian Morearty with:
# * the addition of a mysql_create function (configurable with a guid_generator accessor)
# for much better performance
# * id assignment is now done before_create instead of after_initialize, to more closely
# mimic the default Rails behavior of assigning an id upon save.
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the MIT license.
#
# TO USE
# Install as a plugin in the rails directory vendor/plugin/guid
# define ID as char(22)
# call "usesguid" in ActiveRecord class declaration, like
# class Mymodel < ActiveRecord::Base
# usesguid
#
# if your ID field is not called "ID", call "usesguid :column =>'IdColumnName' "
#
# If you use MySQL as your database, you can make guid generation much faster
# by putting this in config/environment.rb:
# ActiveRecord::Base.guid_generator = :mysql

require 'usesguid'
54 changes: 54 additions & 0 deletions lib/usesguid.rb
@@ -0,0 +1,54 @@
# from Demetrio Nunes
# Modified by Andy Singleton to use different GUID generator
# Further modified by Brian Morearty to:
# 1. optionally use the MySQL GUID generator
# 2. respect the "column" option
# 3. set the id before create instead of after initialize
#
# MIT License

require 'uuid22'
require 'uuid_mysql'

module ActiveRecord
module Usesguid #:nodoc:

def self.append_features(base)
super
base.extend(ClassMethods)
end


module ClassMethods

# guid_generator can be :timestamp or :mysql
def guid_generator=(generator); class_eval { @guid_generator = generator } end
def guid_generator; class_eval { @guid_generator || :timestamp } end

def usesguid(options = {})

class_eval do
set_primary_key options[:column] if options[:column]

before_create :assign_guid

# Give this record a guid id. Public method so people can call it before save if necessary.
def assign_guid
self[self.class.primary_key] ||= case ActiveRecord::Base.guid_generator
when :mysql then UUID.mysql_create(self.connection)
when :timestamp then UUID.timestamp_create()
else raise "Unrecognized guid generator '#{ActiveRecord::Base.guid_generator.to_s}'"
end.to_s22
end

end

end

end
end
end

ActiveRecord::Base.class_eval do
include ActiveRecord::Usesguid
end
43 changes: 43 additions & 0 deletions lib/uuid22.rb
@@ -0,0 +1,43 @@
# Copyright (c) 2005 Assembla, Inc.
# MIT License

require 'uuidtools'

class UUID

# Make an array of 64 URL-safe characters
@@chars64=('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a + ['-','_']
#return a 22 byte URL-safe string, encoded six bits at a time using 64 characters
def to_s22
integer=self.to_i
rval=''
22.times do
c=(integer & 0x3F)
rval+=@@chars64[c]
integer =integer >> 6
end
return rval.reverse
end
# Create a new UUID from a 22char string
def self.parse22(s)
# get the integer representation
integer=0
s.each_byte {|c|
integer = integer << 6
pos=@@chars64.index(c.chr)
integer+=pos
}

time_low = (integer >> 96) & 0xFFFFFFFF
time_mid = (integer >> 80) & 0xFFFF
time_hi_and_version = (integer >> 64) & 0xFFFF
clock_seq_hi_and_reserved = (integer >> 56) & 0xFF
clock_seq_low = (integer >> 48) & 0xFF
nodes = []
for i in 0..5 do
nodes << ((integer >> (40 - (i * 8))) & 0xFF)
end
return new(time_low, time_mid, time_hi_and_version,
clock_seq_hi_and_reserved, clock_seq_low, nodes)
end
end
27 changes: 27 additions & 0 deletions lib/uuid_mysql.rb
@@ -0,0 +1,27 @@
# Copyright (c) 2008 Intuit
# Written by Brian Morearty
# MIT License

require 'uuidtools'

class UUID

BUCKET_SIZE = 50
@@guid_bucket_mutex = Mutex.new
@@guid_bucket = nil

# We'll retrieve a bunch of guids at a time to reduce the # of DB round-trips.
# If the guid bucket is empty, re-fill it by calling MySQL. Then return a guid.
def UUID.mysql_create(connection=ActiveRecord::Base.connection)
raise "UUID.mysql_create only works with MySQL" unless connection.adapter_name.downcase =~ /mysql/
@@guid_bucket_mutex.synchronize do
if @@guid_bucket.blank?
uuid_functions = Array.new(BUCKET_SIZE, "UUID()")
@@guid_bucket = connection.execute("SELECT #{uuid_functions.join(',')}").fetch_row
end
# My tests show shift is much faster than slice!(0), pop, or delete_at(0)
parse @@guid_bucket.shift
end
end

end

0 comments on commit 2dc1e95

Please sign in to comment.