usesguid 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +3 -0
- data/LICENSE +21 -0
- data/README.rdoc +50 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/usesguid/active_record_extensions.rb +52 -0
- data/lib/usesguid/uuid22.rb +43 -0
- data/lib/usesguid/uuid_mysql.rb +27 -0
- data/lib/usesguid/uuidtools.rb +561 -0
- data/lib/usesguid.rb +13 -0
- data/script/console +10 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/usesguid_spec.rb +7 -0
- data/usesguid.gemspec +58 -0
- metadata +82 -0
data/History.txt
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2005 Assembla, Inc.
|
2
|
+
Portions Copyright (c) 2008 Intuit
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
== Changes in this Fork
|
2
|
+
|
3
|
+
* Converted to Gem ported by C. Jason Harrelson (midas)
|
4
|
+
|
5
|
+
|
6
|
+
== DETAILS
|
7
|
+
|
8
|
+
This plugin for ActiveRecord makes the "ID" field into a URL-safe GUID
|
9
|
+
It is a mashup by Andy Singleton <andy@assembla.com> that includes
|
10
|
+
* the UUID class from Bob Aman.
|
11
|
+
* the plugin skeleton from Demetrius Nunes
|
12
|
+
* the 22 character URL-safe format from Andy Singleton
|
13
|
+
You can get standard 36 char UUID formats instead
|
14
|
+
TODO: Auto-detect a character ID field and use a GUID in this case (DRY principle)
|
15
|
+
|
16
|
+
It has been extended by Brian Morearty with:
|
17
|
+
* the addition of a mysql_create function (configurable with a guid_generator accessor)
|
18
|
+
for much better performance
|
19
|
+
* id assignment is now done before_create instead of after_initialize, to more closely
|
20
|
+
mimic the default Rails behavior of assigning an id upon save.
|
21
|
+
|
22
|
+
This library is free software; you can redistribute it and/or modify it
|
23
|
+
under the terms of the MIT license.
|
24
|
+
|
25
|
+
|
26
|
+
== TO USE
|
27
|
+
|
28
|
+
sudo gem install usesguid
|
29
|
+
|
30
|
+
In Rails environment file:
|
31
|
+
|
32
|
+
config.gem "usesguid"
|
33
|
+
|
34
|
+
define ID as char(22)
|
35
|
+
call "usesguid" in ActiveRecord class declaration, like:
|
36
|
+
|
37
|
+
class Mymodel < ActiveRecord::Base
|
38
|
+
usesguid
|
39
|
+
end
|
40
|
+
|
41
|
+
if your ID field is not called "ID", call "usesguid :column =>'IdColumnName' "
|
42
|
+
|
43
|
+
If you use MySQL as your database, you can make guid generation much faster
|
44
|
+
by putting this in config/environment.rb:
|
45
|
+
|
46
|
+
ActiveRecord::Base.guid_generator = :mysql
|
47
|
+
|
48
|
+
== TODO
|
49
|
+
|
50
|
+
* Add tests
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "usesguid"
|
8
|
+
gem.summary = %Q{A much faster version of the usesguid plugin for Rails}
|
9
|
+
gem.description = %Q{A much faster version of the usesguid plugin for Rails (uses MySQL to generate GUIDs)}
|
10
|
+
gem.email = "jason@lookforwardenterprises.com"
|
11
|
+
gem.homepage = "http://github.com/midas/usesguid"
|
12
|
+
gem.authors = ["Brian Morearty","Demetrio Nunes","Robert Aman","C. Jason Harrelson(midas)"]
|
13
|
+
gem.add_development_dependency "rspec"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
if File.exist?('VERSION')
|
40
|
+
version = File.read('VERSION')
|
41
|
+
else
|
42
|
+
version = ""
|
43
|
+
end
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "usesguid #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# from Demetrio Nunes
|
2
|
+
# Modified by Andy Singleton to use different GUID generator
|
3
|
+
# Further modified by Brian Morearty to:
|
4
|
+
# 1. optionally use the MySQL GUID generator
|
5
|
+
# 2. respect the "column" option
|
6
|
+
# 3. set the id before create instead of after initialize
|
7
|
+
#
|
8
|
+
# MIT License
|
9
|
+
|
10
|
+
#require 'uuid22'
|
11
|
+
#require 'uuid_mysql'
|
12
|
+
|
13
|
+
module Usesguid
|
14
|
+
module ActiveRecordExtensions
|
15
|
+
|
16
|
+
#def self.append_features( base )
|
17
|
+
def self.included( base )
|
18
|
+
super
|
19
|
+
base.extend( ClassMethods )
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
|
25
|
+
# guid_generator can be :timestamp or :mysql
|
26
|
+
def guid_generator=(generator); class_eval { @guid_generator = generator } end
|
27
|
+
def guid_generator; class_eval { @guid_generator || :timestamp } end
|
28
|
+
|
29
|
+
def usesguid(options = {})
|
30
|
+
|
31
|
+
class_eval do
|
32
|
+
set_primary_key options[:column] if options[:column]
|
33
|
+
|
34
|
+
before_create :assign_guid
|
35
|
+
|
36
|
+
# Give this record a guid id. Public method so people can call it before save if necessary.
|
37
|
+
def assign_guid
|
38
|
+
self[self.class.primary_key] ||= case ActiveRecord::Base.guid_generator
|
39
|
+
when :mysql then UUID.mysql_create(self.connection)
|
40
|
+
when :timestamp then UUID.timestamp_create()
|
41
|
+
else raise "Unrecognized guid generator '#{ActiveRecord::Base.guid_generator.to_s}'"
|
42
|
+
end.to_s22
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright (c) 2005 Assembla, Inc.
|
2
|
+
# MIT License
|
3
|
+
|
4
|
+
#require 'uuidtools'
|
5
|
+
|
6
|
+
class UUID
|
7
|
+
|
8
|
+
# Make an array of 64 URL-safe characters
|
9
|
+
@@chars64=('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a + ['-','_']
|
10
|
+
#return a 22 byte URL-safe string, encoded six bits at a time using 64 characters
|
11
|
+
def to_s22
|
12
|
+
integer=self.to_i
|
13
|
+
rval=''
|
14
|
+
22.times do
|
15
|
+
c=(integer & 0x3F)
|
16
|
+
rval+=@@chars64[c]
|
17
|
+
integer =integer >> 6
|
18
|
+
end
|
19
|
+
return rval.reverse
|
20
|
+
end
|
21
|
+
# Create a new UUID from a 22char string
|
22
|
+
def self.parse22(s)
|
23
|
+
# get the integer representation
|
24
|
+
integer=0
|
25
|
+
s.each_byte {|c|
|
26
|
+
integer = integer << 6
|
27
|
+
pos=@@chars64.index(c.chr)
|
28
|
+
integer+=pos
|
29
|
+
}
|
30
|
+
|
31
|
+
time_low = (integer >> 96) & 0xFFFFFFFF
|
32
|
+
time_mid = (integer >> 80) & 0xFFFF
|
33
|
+
time_hi_and_version = (integer >> 64) & 0xFFFF
|
34
|
+
clock_seq_hi_and_reserved = (integer >> 56) & 0xFF
|
35
|
+
clock_seq_low = (integer >> 48) & 0xFF
|
36
|
+
nodes = []
|
37
|
+
for i in 0..5 do
|
38
|
+
nodes << ((integer >> (40 - (i * 8))) & 0xFF)
|
39
|
+
end
|
40
|
+
return new(time_low, time_mid, time_hi_and_version,
|
41
|
+
clock_seq_hi_and_reserved, clock_seq_low, nodes)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright (c) 2008 Intuit
|
2
|
+
# Written by Brian Morearty
|
3
|
+
# MIT License
|
4
|
+
|
5
|
+
#require 'uuidtools'
|
6
|
+
|
7
|
+
class UUID
|
8
|
+
|
9
|
+
BUCKET_SIZE = 50
|
10
|
+
@@guid_bucket_mutex = Mutex.new
|
11
|
+
@@guid_bucket = nil
|
12
|
+
|
13
|
+
# We'll retrieve a bunch of guids at a time to reduce the # of DB round-trips.
|
14
|
+
# If the guid bucket is empty, re-fill it by calling MySQL. Then return a guid.
|
15
|
+
def UUID.mysql_create(connection=ActiveRecord::Base.connection)
|
16
|
+
raise "UUID.mysql_create only works with MySQL" unless connection.adapter_name.downcase =~ /mysql/
|
17
|
+
@@guid_bucket_mutex.synchronize do
|
18
|
+
if @@guid_bucket.blank?
|
19
|
+
uuid_functions = Array.new(BUCKET_SIZE, "UUID()")
|
20
|
+
@@guid_bucket = connection.execute("SELECT #{uuid_functions.join(',')}").fetch_row
|
21
|
+
end
|
22
|
+
# My tests show shift is much faster than slice!(0), pop, or delete_at(0)
|
23
|
+
parse @@guid_bucket.shift
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,561 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005 Robert Aman
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
UUID_TOOLS_VERSION = "0.1.3"
|
25
|
+
|
26
|
+
$:.unshift(File.dirname(__FILE__))
|
27
|
+
|
28
|
+
require 'uri'
|
29
|
+
require 'time'
|
30
|
+
require 'thread'
|
31
|
+
require 'digest/sha1'
|
32
|
+
require 'digest/md5'
|
33
|
+
|
34
|
+
# Because it's impossible to hype a UUID generator on its genuine merits,
|
35
|
+
# I give you... Really bad ASCII art in the comments:
|
36
|
+
#
|
37
|
+
#
|
38
|
+
# \
|
39
|
+
# /
|
40
|
+
# +
|
41
|
+
# ]
|
42
|
+
# ]
|
43
|
+
# |
|
44
|
+
# /
|
45
|
+
# Mp___
|
46
|
+
# `~0NNp,
|
47
|
+
# __ggM'
|
48
|
+
# g0M~"`
|
49
|
+
# ]0M*-
|
50
|
+
#
|
51
|
+
# ___
|
52
|
+
# _g000M00g,
|
53
|
+
# j0M~ ~M&
|
54
|
+
# j0M" ~N,
|
55
|
+
# j0P M&
|
56
|
+
# jM 1
|
57
|
+
# j0 ]1
|
58
|
+
# .0P 0,
|
59
|
+
# 00' M&
|
60
|
+
# 0M ]0L
|
61
|
+
# ]0f ___ M0
|
62
|
+
# M0NN0M00MMM~"'M 0&
|
63
|
+
# `~ ~0 ]0,
|
64
|
+
# ]M ]0&
|
65
|
+
# M& M0,
|
66
|
+
# ____gp_ M& M0_
|
67
|
+
# __p0MPM8MM&_ M/ ^0&_
|
68
|
+
# gN"` M0N_j0, MM&__
|
69
|
+
# _gF `~M0P` __ M00g
|
70
|
+
# g0' gM0&, ~M0&
|
71
|
+
# _pM` 0, ]M1 "00&
|
72
|
+
# _00 /g1MMgj01 ]0MI
|
73
|
+
# _0F t"M,7MMM 00I
|
74
|
+
# g0' _ N&j& 40'
|
75
|
+
# g0' _p0Mq_ ' N0QQNM#g,
|
76
|
+
# 0' _g0000000g__ ~M@MMM000g
|
77
|
+
# f _jM00@` ~M0000Mgppg, "P00&
|
78
|
+
# | g000~ `~M000000&_ ~0&
|
79
|
+
# ]M _M00F "00MM` ~#&
|
80
|
+
# `0L m000F #E "0f
|
81
|
+
# 9r j000M` 40, 00
|
82
|
+
# ]0g_ j00M` ^M0MNggp#gqpg M0&
|
83
|
+
# ~MPM0f ~M000000000g_ ,_ygg&M00f
|
84
|
+
# `~~~M00000000000000
|
85
|
+
# `M0000000000f
|
86
|
+
# ~@@@MF~`
|
87
|
+
#
|
88
|
+
#
|
89
|
+
|
90
|
+
#= uuidtools.rb
|
91
|
+
#
|
92
|
+
# UUIDTools was designed to be a simple library for generating any
|
93
|
+
# of the various types of UUIDs. It conforms to RFC 4122 whenever
|
94
|
+
# possible.
|
95
|
+
#
|
96
|
+
#== Example
|
97
|
+
# UUID.md5_create(UUID_DNS_NAMESPACE, "www.widgets.com")
|
98
|
+
# => #<UUID:0x287576 UUID:3d813cbb-47fb-32ba-91df-831e1593ac29>
|
99
|
+
# UUID.sha1_create(UUID_DNS_NAMESPACE, "www.widgets.com")
|
100
|
+
# => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>
|
101
|
+
# UUID.timestamp_create
|
102
|
+
# => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>
|
103
|
+
# UUID.random_create
|
104
|
+
# => #<UUID:0x19013a UUID:984265dc-4200-4f02-ae70-fe4f48964159>
|
105
|
+
class UUID
|
106
|
+
@@last_timestamp = nil
|
107
|
+
@@last_node_id = nil
|
108
|
+
@@last_clock_sequence = nil
|
109
|
+
@@state_file = nil
|
110
|
+
@@mutex = Mutex.new
|
111
|
+
|
112
|
+
def initialize(time_low, time_mid, time_hi_and_version,
|
113
|
+
clock_seq_hi_and_reserved, clock_seq_low, nodes)
|
114
|
+
unless time_low >= 0 && time_low < 4294967296
|
115
|
+
raise ArgumentError,
|
116
|
+
"Expected unsigned 32-bit number for time_low, got #{time_low}."
|
117
|
+
end
|
118
|
+
unless time_mid >= 0 && time_mid < 65536
|
119
|
+
raise ArgumentError,
|
120
|
+
"Expected unsigned 16-bit number for time_mid, got #{time_mid}."
|
121
|
+
end
|
122
|
+
unless time_hi_and_version >= 0 && time_hi_and_version < 65536
|
123
|
+
raise ArgumentError,
|
124
|
+
"Expected unsigned 16-bit number for time_hi_and_version, " +
|
125
|
+
"got #{time_hi_and_version}."
|
126
|
+
end
|
127
|
+
unless clock_seq_hi_and_reserved >= 0 && clock_seq_hi_and_reserved < 256
|
128
|
+
raise ArgumentError,
|
129
|
+
"Expected unsigned 8-bit number for clock_seq_hi_and_reserved, " +
|
130
|
+
"got #{clock_seq_hi_and_reserved}."
|
131
|
+
end
|
132
|
+
unless clock_seq_low >= 0 && clock_seq_low < 256
|
133
|
+
raise ArgumentError,
|
134
|
+
"Expected unsigned 8-bit number for clock_seq_low, " +
|
135
|
+
"got #{clock_seq_low}."
|
136
|
+
end
|
137
|
+
unless nodes.respond_to? :size
|
138
|
+
raise ArgumentError,
|
139
|
+
"Expected nodes to respond to :size."
|
140
|
+
end
|
141
|
+
unless nodes.size == 6
|
142
|
+
raise ArgumentError,
|
143
|
+
"Expected nodes to have size of 6."
|
144
|
+
end
|
145
|
+
for node in nodes
|
146
|
+
unless node >= 0 && node < 256
|
147
|
+
raise ArgumentError,
|
148
|
+
"Expected unsigned 8-bit number for each node, " +
|
149
|
+
"got #{node}."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
@time_low = time_low
|
153
|
+
@time_mid = time_mid
|
154
|
+
@time_hi_and_version = time_hi_and_version
|
155
|
+
@clock_seq_hi_and_reserved = clock_seq_hi_and_reserved
|
156
|
+
@clock_seq_low = clock_seq_low
|
157
|
+
@nodes = nodes
|
158
|
+
end
|
159
|
+
|
160
|
+
attr_accessor :time_low
|
161
|
+
attr_accessor :time_mid
|
162
|
+
attr_accessor :time_hi_and_version
|
163
|
+
attr_accessor :clock_seq_hi_and_reserved
|
164
|
+
attr_accessor :clock_seq_low
|
165
|
+
attr_accessor :nodes
|
166
|
+
|
167
|
+
# Parses a UUID from a string.
|
168
|
+
def UUID.parse(uuid_string)
|
169
|
+
unless uuid_string.kind_of? String
|
170
|
+
raise ArgumentError,
|
171
|
+
"Expected String, got #{uuid_string.class.name} instead."
|
172
|
+
end
|
173
|
+
uuid_components = uuid_string.downcase.scan(
|
174
|
+
Regexp.new("^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-" +
|
175
|
+
"([0-9a-f]{2})([0-9a-f]{2})-([0-9a-f]{12})$")).first
|
176
|
+
raise ArgumentError, "Invalid UUID format." if uuid_components.nil?
|
177
|
+
time_low = uuid_components[0].to_i(16)
|
178
|
+
time_mid = uuid_components[1].to_i(16)
|
179
|
+
time_hi_and_version = uuid_components[2].to_i(16)
|
180
|
+
clock_seq_hi_and_reserved = uuid_components[3].to_i(16)
|
181
|
+
clock_seq_low = uuid_components[4].to_i(16)
|
182
|
+
nodes = []
|
183
|
+
for i in 0..5
|
184
|
+
nodes << uuid_components[5][(i * 2)..(i * 2) + 1].to_i(16)
|
185
|
+
end
|
186
|
+
return UUID.new(time_low, time_mid, time_hi_and_version,
|
187
|
+
clock_seq_hi_and_reserved, clock_seq_low, nodes)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Parses a UUID from a raw byte string.
|
191
|
+
def UUID.parse_raw(raw_string)
|
192
|
+
unless raw_string.kind_of? String
|
193
|
+
raise ArgumentError,
|
194
|
+
"Expected String, got #{raw_string.class.name} instead."
|
195
|
+
end
|
196
|
+
integer = UUID.convert_byte_string_to_int(raw_string)
|
197
|
+
|
198
|
+
time_low = (integer >> 96) & 0xFFFFFFFF
|
199
|
+
time_mid = (integer >> 80) & 0xFFFF
|
200
|
+
time_hi_and_version = (integer >> 64) & 0xFFFF
|
201
|
+
clock_seq_hi_and_reserved = (integer >> 56) & 0xFF
|
202
|
+
clock_seq_low = (integer >> 48) & 0xFF
|
203
|
+
nodes = []
|
204
|
+
for i in 0..5
|
205
|
+
nodes << ((integer >> (40 - (i * 8))) & 0xFF)
|
206
|
+
end
|
207
|
+
return UUID.new(time_low, time_mid, time_hi_and_version,
|
208
|
+
clock_seq_hi_and_reserved, clock_seq_low, nodes)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Creates a UUID from a random value.
|
212
|
+
def UUID.random_create()
|
213
|
+
new_uuid = UUID.parse_raw(UUID.true_random)
|
214
|
+
new_uuid.time_hi_and_version &= 0x0FFF
|
215
|
+
new_uuid.time_hi_and_version |= (4 << 12)
|
216
|
+
new_uuid.clock_seq_hi_and_reserved &= 0x3F
|
217
|
+
new_uuid.clock_seq_hi_and_reserved |= 0x80
|
218
|
+
return new_uuid
|
219
|
+
end
|
220
|
+
|
221
|
+
# Creates a UUID from a timestamp.
|
222
|
+
def UUID.timestamp_create(timestamp=nil)
|
223
|
+
# We need a lock here to prevent two threads from ever
|
224
|
+
# getting the same timestamp.
|
225
|
+
@@mutex.synchronize do
|
226
|
+
# Always use GMT to generate UUIDs.
|
227
|
+
if timestamp.nil?
|
228
|
+
gmt_timestamp = Time.now.gmtime
|
229
|
+
else
|
230
|
+
gmt_timestamp = timestamp.gmtime
|
231
|
+
end
|
232
|
+
# Convert to 100 nanosecond blocks
|
233
|
+
gmt_timestamp_100_nanoseconds = (gmt_timestamp.tv_sec * 10000000) +
|
234
|
+
(gmt_timestamp.tv_usec * 10) + 0x01B21DD213814000
|
235
|
+
nodes = UUID.get_mac_address.split(":").collect do |octet|
|
236
|
+
octet.to_i(16)
|
237
|
+
end
|
238
|
+
node_id = 0
|
239
|
+
for i in 0..5
|
240
|
+
node_id += (nodes[i] << (40 - (i * 8)))
|
241
|
+
end
|
242
|
+
clock_sequence = @@last_clock_sequence
|
243
|
+
if clock_sequence.nil?
|
244
|
+
clock_sequence = UUID.convert_byte_string_to_int(UUID.true_random)
|
245
|
+
end
|
246
|
+
if @@last_node_id != nil && @@last_node_id != node_id
|
247
|
+
# The node id has changed. Change the clock id.
|
248
|
+
clock_sequence = UUID.convert_byte_string_to_int(UUID.true_random)
|
249
|
+
elsif @@last_timestamp != nil &&
|
250
|
+
gmt_timestamp_100_nanoseconds < @@last_timestamp
|
251
|
+
clock_sequence = clock_sequence + 1
|
252
|
+
end
|
253
|
+
@@last_timestamp = gmt_timestamp_100_nanoseconds
|
254
|
+
@@last_node_id = node_id
|
255
|
+
@@last_clock_sequence = clock_sequence
|
256
|
+
|
257
|
+
time_low = gmt_timestamp_100_nanoseconds & 0xFFFFFFFF
|
258
|
+
time_mid = ((gmt_timestamp_100_nanoseconds >> 32) & 0xFFFF)
|
259
|
+
time_hi_and_version = ((gmt_timestamp_100_nanoseconds >> 48) & 0x0FFF)
|
260
|
+
time_hi_and_version |= (1 << 12)
|
261
|
+
clock_seq_low = clock_sequence & 0xFF;
|
262
|
+
clock_seq_hi_and_reserved = (clock_sequence & 0x3F00) >> 8
|
263
|
+
clock_seq_hi_and_reserved |= 0x80
|
264
|
+
|
265
|
+
return UUID.new(time_low, time_mid, time_hi_and_version,
|
266
|
+
clock_seq_hi_and_reserved, clock_seq_low, nodes)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Creates a UUID using the MD5 hash. (Version 3)
|
271
|
+
def UUID.md5_create(namespace, name)
|
272
|
+
return UUID.create_from_hash(Digest::MD5, namespace, name)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Creates a UUID using the SHA1 hash. (Version 5)
|
276
|
+
def UUID.sha1_create(namespace, name)
|
277
|
+
return UUID.create_from_hash(Digest::SHA1, namespace, name)
|
278
|
+
end
|
279
|
+
|
280
|
+
# This method applies only to version 1 UUIDs.
|
281
|
+
# Checks if the node ID was generated from a random number
|
282
|
+
# or from an IEEE 802 address (MAC address).
|
283
|
+
# Always returns false for UUIDs that aren't version 1.
|
284
|
+
# This should not be confused with version 4 UUIDs where
|
285
|
+
# more than just the node id is random.
|
286
|
+
def random_node_id?
|
287
|
+
return false if self.version != 1
|
288
|
+
return ((self.nodes.first & 0x01) == 1)
|
289
|
+
end
|
290
|
+
|
291
|
+
# Returns true if this UUID is the
|
292
|
+
# nil UUID (00000000-0000-0000-0000-000000000000).
|
293
|
+
def nil_uuid?
|
294
|
+
return false if self.time_low != 0
|
295
|
+
return false if self.time_mid != 0
|
296
|
+
return false if self.time_hi_and_version != 0
|
297
|
+
return false if self.clock_seq_hi_and_reserved != 0
|
298
|
+
return false if self.clock_seq_low != 0
|
299
|
+
self.nodes.each do |node|
|
300
|
+
return false if node != 0
|
301
|
+
end
|
302
|
+
return true
|
303
|
+
end
|
304
|
+
|
305
|
+
# Returns the UUID version type.
|
306
|
+
# Possible values:
|
307
|
+
# 1 - Time-based with unique or random host identifier
|
308
|
+
# 2 - DCE Security version (with POSIX UIDs)
|
309
|
+
# 3 - Name-based (MD5 hash)
|
310
|
+
# 4 - Random
|
311
|
+
# 5 - Name-based (SHA-1 hash)
|
312
|
+
def version
|
313
|
+
return (time_hi_and_version >> 12)
|
314
|
+
end
|
315
|
+
|
316
|
+
# Returns the UUID variant.
|
317
|
+
# Possible values:
|
318
|
+
# 0b000 - Reserved, NCS backward compatibility.
|
319
|
+
# 0b100 - The variant specified in this document.
|
320
|
+
# 0b110 - Reserved, Microsoft Corporation backward compatibility.
|
321
|
+
# 0b111 - Reserved for future definition.
|
322
|
+
def variant
|
323
|
+
variant_raw = (clock_seq_hi_and_reserved >> 5)
|
324
|
+
result = nil
|
325
|
+
if (variant_raw >> 2) == 0
|
326
|
+
result = 0x000
|
327
|
+
elsif (variant_raw >> 1) == 2
|
328
|
+
result = 0x100
|
329
|
+
else
|
330
|
+
result = variant_raw
|
331
|
+
end
|
332
|
+
return (result >> 6)
|
333
|
+
end
|
334
|
+
|
335
|
+
# Returns true if this UUID is valid.
|
336
|
+
def valid?
|
337
|
+
if [0b000, 0b100, 0b110, 0b111].include?(self.variant) &&
|
338
|
+
(1..5).include?(self.version)
|
339
|
+
return true
|
340
|
+
else
|
341
|
+
return false
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
# Returns the IEEE 802 address used to generate this UUID or
|
346
|
+
# nil if a MAC address was not used.
|
347
|
+
def mac_address
|
348
|
+
return nil if self.version != 1
|
349
|
+
return nil if self.random_node_id?
|
350
|
+
return (self.nodes.collect do |node|
|
351
|
+
sprintf("%2.2x", node)
|
352
|
+
end).join(":")
|
353
|
+
end
|
354
|
+
|
355
|
+
# Returns the timestamp used to generate this UUID
|
356
|
+
def timestamp
|
357
|
+
return nil if self.version != 1
|
358
|
+
gmt_timestamp_100_nanoseconds = 0
|
359
|
+
gmt_timestamp_100_nanoseconds +=
|
360
|
+
((self.time_hi_and_version & 0x0FFF) << 48)
|
361
|
+
gmt_timestamp_100_nanoseconds += (self.time_mid << 32)
|
362
|
+
gmt_timestamp_100_nanoseconds += self.time_low
|
363
|
+
return Time.at(
|
364
|
+
(gmt_timestamp_100_nanoseconds - 0x01B21DD213814000) / 10000000.0)
|
365
|
+
end
|
366
|
+
|
367
|
+
# Compares two UUIDs lexically
|
368
|
+
def <=>(other_uuid)
|
369
|
+
check = self.time_low <=> other_uuid.time_low
|
370
|
+
return check if check != 0
|
371
|
+
check = self.time_mid <=> other_uuid.time_mid
|
372
|
+
return check if check != 0
|
373
|
+
check = self.time_hi_and_version <=> other_uuid.time_hi_and_version
|
374
|
+
return check if check != 0
|
375
|
+
check = self.clock_seq_hi_and_reserved <=>
|
376
|
+
other_uuid.clock_seq_hi_and_reserved
|
377
|
+
return check if check != 0
|
378
|
+
check = self.clock_seq_low <=> other_uuid.clock_seq_low
|
379
|
+
return check if check != 0
|
380
|
+
for i in 0..5
|
381
|
+
if (self.nodes[i] < other_uuid.nodes[i])
|
382
|
+
return -1
|
383
|
+
end
|
384
|
+
if (self.nodes[i] > other_uuid.nodes[i])
|
385
|
+
return 1
|
386
|
+
end
|
387
|
+
end
|
388
|
+
return 0
|
389
|
+
end
|
390
|
+
|
391
|
+
# Returns a representation of the object's state
|
392
|
+
def inspect
|
393
|
+
return "#<UUID:0x#{self.object_id.to_s(16)} UUID:#{self.to_s}>"
|
394
|
+
end
|
395
|
+
|
396
|
+
# Returns the hex digest of the UUID object.
|
397
|
+
def hexdigest
|
398
|
+
return self.to_i.to_s(16)
|
399
|
+
end
|
400
|
+
|
401
|
+
# Returns the raw bytes that represent this UUID.
|
402
|
+
def raw
|
403
|
+
return UUID.convert_int_to_byte_string(self.to_i, 16)
|
404
|
+
end
|
405
|
+
|
406
|
+
# Returns a string representation for this UUID.
|
407
|
+
def to_s
|
408
|
+
result = sprintf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", @time_low, @time_mid,
|
409
|
+
@time_hi_and_version, @clock_seq_hi_and_reserved, @clock_seq_low);
|
410
|
+
for i in 0..5
|
411
|
+
result << sprintf("%2.2x", @nodes[i])
|
412
|
+
end
|
413
|
+
return result
|
414
|
+
end
|
415
|
+
|
416
|
+
# Returns an integer representation for this UUID.
|
417
|
+
def to_i
|
418
|
+
bytes = (time_low << 96) + (time_mid << 80) +
|
419
|
+
(time_hi_and_version << 64) + (clock_seq_hi_and_reserved << 56) +
|
420
|
+
(clock_seq_low << 48)
|
421
|
+
for i in 0..5
|
422
|
+
bytes += (nodes[i] << (40 - (i * 8)))
|
423
|
+
end
|
424
|
+
return bytes
|
425
|
+
end
|
426
|
+
|
427
|
+
# Returns a URI for this UUID.
|
428
|
+
def to_uri
|
429
|
+
return URI.parse(self.to_uri_string)
|
430
|
+
end
|
431
|
+
|
432
|
+
# Returns a URI string for this UUID.
|
433
|
+
def to_uri_string
|
434
|
+
return "urn:uuid:#{self.to_s}"
|
435
|
+
end
|
436
|
+
|
437
|
+
def UUID.create_from_hash(hash_class, namespace, name) #:nodoc:
|
438
|
+
if hash_class == Digest::MD5
|
439
|
+
version = 3
|
440
|
+
elsif hash_class == Digest::SHA1
|
441
|
+
version = 5
|
442
|
+
else
|
443
|
+
raise ArgumentError,
|
444
|
+
"Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
|
445
|
+
end
|
446
|
+
hash = hash_class.new
|
447
|
+
hash.update(namespace.raw)
|
448
|
+
hash.update(name)
|
449
|
+
hash_string = hash.to_s[0..31]
|
450
|
+
new_uuid = UUID.parse("#{hash_string[0..7]}-#{hash_string[8..11]}-" +
|
451
|
+
"#{hash_string[12..15]}-#{hash_string[16..19]}-#{hash_string[20..31]}")
|
452
|
+
|
453
|
+
new_uuid.time_hi_and_version &= 0x0FFF
|
454
|
+
new_uuid.time_hi_and_version |= (version << 12)
|
455
|
+
new_uuid.clock_seq_hi_and_reserved &= 0x3F
|
456
|
+
new_uuid.clock_seq_hi_and_reserved |= 0x80
|
457
|
+
return new_uuid
|
458
|
+
end
|
459
|
+
|
460
|
+
# Returns the MAC address of the current computer's network card.
|
461
|
+
# Returns nil if a MAC address could not be found.
|
462
|
+
def UUID.get_mac_address #:nodoc:
|
463
|
+
if RUBY_PLATFORM =~ /win/ && !(RUBY_PLATFORM =~ /darwin/)
|
464
|
+
begin
|
465
|
+
ifconfig_output = `ipconfig /all`
|
466
|
+
mac_addresses = ifconfig_output.scan(
|
467
|
+
Regexp.new("(#{(["[0-9A-F]{2}"] * 6).join("-")})"))
|
468
|
+
if mac_addresses.size > 0
|
469
|
+
return mac_addresses.first.first.downcase.gsub(/-/, ":")
|
470
|
+
end
|
471
|
+
rescue
|
472
|
+
end
|
473
|
+
else
|
474
|
+
begin
|
475
|
+
ifconfig_output = `ifconfig`
|
476
|
+
mac_addresses = ifconfig_output.scan(
|
477
|
+
Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
|
478
|
+
if mac_addresses.size == 0
|
479
|
+
ifconfig_output = `ifconfig | grep HWaddr | cut -c39-`
|
480
|
+
mac_addresses = ifconfig_output.scan(
|
481
|
+
Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
|
482
|
+
end
|
483
|
+
if mac_addresses.size == 0
|
484
|
+
ifconfig_output = `/sbin/ifconfig`
|
485
|
+
mac_addresses = ifconfig_output.scan(
|
486
|
+
Regexp.new("ether (#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
|
487
|
+
end
|
488
|
+
if mac_addresses.size == 0
|
489
|
+
ifconfig_output = `/sbin/ifconfig | grep HWaddr | cut -c39-`
|
490
|
+
mac_addresses = ifconfig_output.scan(
|
491
|
+
Regexp.new("(#{(["[0-9a-fA-F]{2}"] * 6).join(":")})"))
|
492
|
+
end
|
493
|
+
if mac_addresses.size > 0
|
494
|
+
return mac_addresses.first.first
|
495
|
+
end
|
496
|
+
rescue
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
# Returns 128 bits of highly unpredictable data.
|
502
|
+
# The random number generator isn't perfect, but it's
|
503
|
+
# much, much better than the built-in pseudorandom number generators.
|
504
|
+
def UUID.true_random #:nodoc:
|
505
|
+
require 'benchmark'
|
506
|
+
hash = Digest::SHA1.new
|
507
|
+
performance = Benchmark.measure do
|
508
|
+
hash.update(rand.to_s)
|
509
|
+
hash.update(srand.to_s)
|
510
|
+
hash.update(rand.to_s)
|
511
|
+
hash.update(srand.to_s)
|
512
|
+
hash.update(Time.now.to_s)
|
513
|
+
hash.update(rand.to_s)
|
514
|
+
hash.update(self.object_id.to_s)
|
515
|
+
hash.update(rand.to_s)
|
516
|
+
hash.update(hash.object_id.to_s)
|
517
|
+
hash.update(self.methods.inspect)
|
518
|
+
begin
|
519
|
+
random_device = nil
|
520
|
+
if File.exists? "/dev/urandom"
|
521
|
+
random_device = File.open "/dev/urandom", "r"
|
522
|
+
elsif File.exists? "/dev/random"
|
523
|
+
random_device = File.open "/dev/random", "r"
|
524
|
+
end
|
525
|
+
hash.update(random_device.read(20)) if random_device != nil
|
526
|
+
rescue
|
527
|
+
end
|
528
|
+
begin
|
529
|
+
srand(hash.to_s.to_i(16) >> 128)
|
530
|
+
rescue
|
531
|
+
end
|
532
|
+
hash.update(rand.to_s)
|
533
|
+
hash.update(UUID.true_random) if (rand(2) == 0)
|
534
|
+
end
|
535
|
+
hash.update(performance.real.to_s)
|
536
|
+
hash.update(performance.inspect)
|
537
|
+
return UUID.convert_int_to_byte_string(hash.to_s[4..35].to_i(16), 16)
|
538
|
+
end
|
539
|
+
|
540
|
+
def UUID.convert_int_to_byte_string(integer, size) #:nodoc:
|
541
|
+
byte_string = ""
|
542
|
+
for i in 0..(size - 1)
|
543
|
+
byte_string << ((integer >> (((size - 1) - i) * 8)) & 0xFF)
|
544
|
+
end
|
545
|
+
return byte_string
|
546
|
+
end
|
547
|
+
|
548
|
+
def UUID.convert_byte_string_to_int(byte_string) #:nodoc:
|
549
|
+
integer = 0
|
550
|
+
size = byte_string.size
|
551
|
+
for i in 0..(size - 1)
|
552
|
+
integer += (byte_string[i] << (((size - 1) - i) * 8))
|
553
|
+
end
|
554
|
+
return integer
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
UUID_DNS_NAMESPACE = UUID.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
|
559
|
+
UUID_URL_NAMESPACE = UUID.parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
|
560
|
+
UUID_OID_NAMESPACE = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
|
561
|
+
UUID_X500_NAMESPACE = UUID.parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
|
data/lib/usesguid.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'usesguid/active_record_extensions'
|
5
|
+
require 'usesguid/uuid22'
|
6
|
+
require 'usesguid/uuid_mysql'
|
7
|
+
require 'usesguid/uuidtools'
|
8
|
+
|
9
|
+
module Usesguid
|
10
|
+
VERSION = '1.0.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
ActiveRecord::Base.class_eval { include Usesguid::ActiveRecordExtensions } if defined?( ActiveRecord::Base )
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/usesguid.rb'}"
|
9
|
+
puts "Loading usesguid gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/spec/spec_helper.rb
ADDED
data/usesguid.gemspec
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{usesguid}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brian Morearty", "Demetrio Nunes", "Robert Aman", "C. Jason Harrelson(midas)"]
|
12
|
+
s.date = %q{2009-11-13}
|
13
|
+
s.description = %q{A much faster version of the usesguid plugin for Rails (uses MySQL to generate GUIDs)}
|
14
|
+
s.email = %q{jason@lookforwardenterprises.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"History.txt",
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/usesguid.rb",
|
26
|
+
"lib/usesguid/active_record_extensions.rb",
|
27
|
+
"lib/usesguid/uuid22.rb",
|
28
|
+
"lib/usesguid/uuid_mysql.rb",
|
29
|
+
"lib/usesguid/uuidtools.rb",
|
30
|
+
"script/console",
|
31
|
+
"spec/spec_helper.rb",
|
32
|
+
"spec/usesguid_spec.rb",
|
33
|
+
"usesguid.gemspec"
|
34
|
+
]
|
35
|
+
s.homepage = %q{http://github.com/midas/usesguid}
|
36
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
+
s.require_paths = ["lib"]
|
38
|
+
s.rubygems_version = %q{1.3.5}
|
39
|
+
s.summary = %q{A much faster version of the usesguid plugin for Rails}
|
40
|
+
s.test_files = [
|
41
|
+
"spec/spec_helper.rb",
|
42
|
+
"spec/usesguid_spec.rb"
|
43
|
+
]
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
+
s.specification_version = 3
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: usesguid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Morearty
|
8
|
+
- Demetrio Nunes
|
9
|
+
- Robert Aman
|
10
|
+
- C. Jason Harrelson(midas)
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
|
15
|
+
date: 2009-11-13 00:00:00 -06:00
|
16
|
+
default_executable:
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: rspec
|
20
|
+
type: :development
|
21
|
+
version_requirement:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: "0"
|
27
|
+
version:
|
28
|
+
description: A much faster version of the usesguid plugin for Rails (uses MySQL to generate GUIDs)
|
29
|
+
email: jason@lookforwardenterprises.com
|
30
|
+
executables: []
|
31
|
+
|
32
|
+
extensions: []
|
33
|
+
|
34
|
+
extra_rdoc_files:
|
35
|
+
- LICENSE
|
36
|
+
- README.rdoc
|
37
|
+
files:
|
38
|
+
- History.txt
|
39
|
+
- LICENSE
|
40
|
+
- README.rdoc
|
41
|
+
- Rakefile
|
42
|
+
- VERSION
|
43
|
+
- lib/usesguid.rb
|
44
|
+
- lib/usesguid/active_record_extensions.rb
|
45
|
+
- lib/usesguid/uuid22.rb
|
46
|
+
- lib/usesguid/uuid_mysql.rb
|
47
|
+
- lib/usesguid/uuidtools.rb
|
48
|
+
- script/console
|
49
|
+
- spec/spec_helper.rb
|
50
|
+
- spec/usesguid_spec.rb
|
51
|
+
- usesguid.gemspec
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/midas/usesguid
|
54
|
+
licenses: []
|
55
|
+
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options:
|
58
|
+
- --charset=UTF-8
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: A much faster version of the usesguid plugin for Rails
|
80
|
+
test_files:
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/usesguid_spec.rb
|