with_uuid 0.1.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb9642c8c8bb5bf5889dc9484c0474ddec605305
4
+ data.tar.gz: 649122cc58a2d70e333f864f09eda84735a4d0ac
5
+ SHA512:
6
+ metadata.gz: d5dd1ad095df47e61c6c688506a94ae59b8db614fdd2602d9762b29829e196a5664dddd73e80ce45b2825c283bd12df626bb19db24935f5e486e4a55f3951a35
7
+ data.tar.gz: e1185f43899ed56948be28b333bac1ef0b44aece1e2e464b18b571e16fb26187afa088933f39a38384f6e28aa33713ee27950d99a00cc046953e56523657628f
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ gemdev
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p247
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in has_uuid.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jason Harrelson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # HasUuid
2
+
3
+ Provides facilities to utilize UUIDs with ActiveRecord, including model and migration extensions.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'has_uuid'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install has_uuid
19
+
20
+
21
+ ## Usage
22
+
23
+ In a migration:
24
+
25
+ create_table "comments", :id => false, :force => true do |t|
26
+ t.uuid "id", :primary_key => true
27
+ t.uuid "post_id", :null => false
28
+ end
29
+
30
+ In a model:
31
+
32
+ class Posts < ActiveRecord::Base
33
+ include WithUuid::Model
34
+
35
+ # ...
36
+ end
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,131 @@
1
+ module ActiveRecord
2
+ # = Active Record Schema Dumper
3
+ #
4
+ # This class is used to dump the database schema for some connection to some
5
+ # output format (i.e., ActiveRecord::Schema).
6
+ class SchemaDumper #:nodoc:
7
+ private
8
+
9
+ def uuid_sql_types
10
+ [
11
+ 'varchar(36)',
12
+ 'uniqueidentifier'
13
+ ]
14
+ end
15
+
16
+ def table(table, stream)
17
+ columns = @connection.columns(table)
18
+ begin
19
+ tbl = StringIO.new
20
+
21
+ # first dump primary key column
22
+ pk = nil
23
+ if @connection.respond_to?(:pk_and_sequence_for)
24
+ pk, _ = @connection.pk_and_sequence_for(table)
25
+ end
26
+ if @connection.respond_to?(:primary_key) && pk.nil?
27
+ pk = @connection.primary_key(table)
28
+ end
29
+
30
+ tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}"
31
+ if pk_col = columns.detect { |c| c.name == pk }
32
+ if pk != 'id'
33
+ tbl.print %Q(, :primary_key => "#{pk}")
34
+ end
35
+ if uuid_sql_types.include?( pk_col.sql_type )
36
+ tbl.print ", :id => false"
37
+ end
38
+ else
39
+ tbl.print ", :id => false"
40
+ end
41
+ tbl.print ", :force => true"
42
+ tbl.puts " do |t|"
43
+
44
+ # then dump all non-primary key columns
45
+ column_specs = columns.map do |column|
46
+ raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
47
+ next if column.name == pk
48
+ spec = {}
49
+ spec[:name] = column.name.inspect
50
+
51
+ #debugger if column.name.include?( 'id' )
52
+ # AR has an optimization which handles zero-scale decimals as integers. This
53
+ # code ensures that the dumper still dumps the column as a decimal.
54
+ spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
55
+ 'decimal'
56
+ elsif uuid_sql_types.include?( column.sql_type ) && !column.primary
57
+ 'uuid'
58
+ else
59
+ column.type.to_s
60
+ end
61
+ unless spec[:type] == 'uuid'
62
+ spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
63
+ spec[:precision] = column.precision.inspect if column.precision
64
+ spec[:scale] = column.scale.inspect if column.scale
65
+ spec[:default] = default_string(column.default) if column.has_default?
66
+ end
67
+ spec[:null] = 'false' unless column.null
68
+ (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
69
+ spec
70
+ end.compact
71
+
72
+ # add PK column spec if UUID
73
+ if pk_col && uuid_sql_types.include?( pk_col.sql_type )
74
+ pk_spec = {}
75
+ pk_spec[:name] = pk_col.name.inspect
76
+
77
+ pk_spec[:type] = if uuid_sql_types.include?( pk_col.sql_type )
78
+ 'uuid'
79
+ else
80
+ pk_col.type.to_s
81
+ end
82
+
83
+ pk_spec[:primary_key] = 'true'
84
+ pk_spec[:null] = 'false' unless pk_col.null
85
+ pk_spec[:default] = default_string(pk_col.default) if pk_col.has_default?
86
+ (pk_spec.keys - [:name, :type]).each{ |k| pk_spec[k].insert(0, "#{k.inspect} => ")}
87
+ column_specs.insert( 0, pk_spec )
88
+ end
89
+
90
+ # find all migration keys used in this table
91
+ keys = [:name, :limit, :precision, :scale, :default, :null, :primary_key] & column_specs.map{ |k| k.keys }.flatten
92
+
93
+ # figure out the lengths for each column based on above keys
94
+ lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
95
+
96
+ # the string we're going to sprintf our values against, with standardized column widths
97
+ format_string = lengths.map{ |len| "%-#{len}s" }
98
+
99
+ # find the max length for the 'type' column, which is special
100
+ type_length = column_specs.map{ |column| column[:type].length }.max
101
+
102
+ # add column type definition to our format string
103
+ format_string.unshift " t.%-#{type_length}s "
104
+
105
+ format_string *= ''
106
+
107
+ column_specs.each do |colspec|
108
+ values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
109
+ values.unshift colspec[:type]
110
+ tbl.print((format_string % values).gsub(/,\s*$/, ''))
111
+ tbl.puts
112
+ end
113
+
114
+ tbl.puts " end"
115
+ tbl.puts
116
+
117
+ indexes(table, tbl)
118
+
119
+ tbl.rewind
120
+ stream.print tbl.read
121
+ rescue => e
122
+ stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
123
+ stream.puts "# #{e.message}"
124
+ stream.puts
125
+ end
126
+
127
+ stream
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,63 @@
1
+ module WithUuid
2
+ class CombUuid
3
+
4
+ def initialize( uuid_str )
5
+ @uuid_str = uuid_str
6
+ end
7
+
8
+ def to_s
9
+ uuid_str
10
+ end
11
+
12
+ def parts
13
+ @parts ||= @uuid_str.split( '-' )
14
+ end
15
+
16
+ def []( idx )
17
+ parts[idx]
18
+ end
19
+
20
+ def first
21
+ parts[0]
22
+ end
23
+
24
+ def last
25
+ parts[4]
26
+ end
27
+
28
+ def self.uuid
29
+ # See:
30
+ # http://stackoverflow.com/questions/7747145/is-comb-guid-a-good-idea-with-rails-3-1-if-i-use-guids-for-primary-keys
31
+ # http://www.codeproject.com/Articles/32597/Performance-Comparison-Identity-x-NewId-x-NewSeque
32
+
33
+ # MS SQL syntax: SELECT CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
34
+
35
+ # Get current Time object
36
+ utc_timestamp = Time.now.utc
37
+
38
+ # Convert to integer with milliseconds: (Seconds since Epoch * 1000) + (6-digit microsecond fraction / 1000)
39
+ utc_timestamp_with_ms_int = (utc_timestamp.tv_sec * 1000) + (utc_timestamp.tv_usec / 1000)
40
+
41
+ # Format as hex, minimum of 12 digits, with leading zero. Note that 12 hex digits handles to year 10889 (*).
42
+ utc_timestamp_with_ms_hexstring = "%012x" % utc_timestamp_with_ms_int
43
+
44
+ # If we supply UUIDTOOLS with a MAC address, it will use that rather than retrieving from system.
45
+ # Use a regular expression to split into array, then insert ":" characters so it "looks" like a MAC address.
46
+ UUIDTools::UUID.mac_address = (utc_timestamp_with_ms_hexstring.scan( /.{2}/ )).join(":")
47
+
48
+ # Generate Version 1 UUID (see RFC 4122).
49
+ uuid_str = UUIDTools::UUID.timestamp_create().to_s.upcase
50
+
51
+ # (*) A note on maximum time handled by 6-byte timestamp that includes milliseconds:
52
+ # If utc_timestamp_with_ms_hexstring = "FFFFFFFFFFFF" (12 F's), then
53
+ # Time.at(Float(utc_timestamp_with_ms_hexstring.hex)/1000).utc.iso8601(10) = "10889-08-02T05:31:50.6550292968Z".
54
+
55
+ self.new( uuid_str )
56
+ end
57
+
58
+ protected
59
+
60
+ attr_reader :uuid_str
61
+
62
+ end
63
+ end
@@ -0,0 +1,30 @@
1
+ require 'active_record'
2
+
3
+ module WithUuid
4
+ module Extensions
5
+
6
+ module Migrations
7
+
8
+ def uuid(*column_names)
9
+ options = column_names.extract_options!
10
+ column_names.each do |name|
11
+ type = case(@base.adapter_name.downcase)
12
+ when 'sqlserver'
13
+ 'uniqueidentifier'
14
+ when 'postgresql'
15
+ 'uuid'
16
+ else
17
+ 'varchar(36)'
18
+ end
19
+ column(name, "#{type}#{' PRIMARY KEY' if options.delete(:primary_key)}", options)
20
+ end
21
+ end
22
+
23
+ def uuid_fk(*column_names)
24
+ uuid( *column_names )
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ module WithUuid
2
+ module Extensions
3
+
4
+ autoload :Migrations, 'with_uuid/extensions/migrations'
5
+
6
+ def self.apply!
7
+ if defined? ActiveRecord::ConnectionAdapters::Table
8
+ ActiveRecord::ConnectionAdapters::Table.send :include, WithUuid::Extensions::Migrations
9
+ end
10
+ if defined? ActiveRecord::ConnectionAdapters::TableDefinition
11
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, WithUuid::Extensions::Migrations
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ require "active_support/concern"
2
+
3
+ module WithUuid
4
+ module Model
5
+
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+
10
+ self.primary_key = :id
11
+
12
+ before_validation :set_id
13
+
14
+ end
15
+
16
+ def set_id
17
+ return unless id.blank?
18
+
19
+ # Assign generated COMBination GUID to #id
20
+ write_attribute( :id, WithUuid::CombUuid.uuid.to_s )
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ require 'with_uuid'
2
+ require 'rails'
3
+
4
+ module WithUuid
5
+ class Railtie < Rails::Railtie
6
+ railtie_name :with_uuid
7
+
8
+ config.to_prepare do
9
+ WithUuid::Extensions.apply!
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module WithUuid
2
+ VERSION = "0.1.2"
3
+ end
data/lib/with_uuid.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'with_uuid/railtie' if defined?(Rails::Railtie)
2
+ require "with_uuid/version"
3
+ require 'schema_dumper'
4
+ require 'uuidtools'
5
+
6
+ module WithUuid
7
+
8
+ autoload :CombUuid, 'with_uuid/comb_uuid'
9
+ autoload :Extensions, 'with_uuid/extensions'
10
+ autoload :Model, 'with_uuid/model'
11
+
12
+ end
data/with_uuid.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'with_uuid/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "with_uuid"
8
+ spec.version = WithUuid::VERSION
9
+ spec.authors = ["Jason Harrelson"]
10
+ spec.email = ["cjharrelson@iberon.com"]
11
+ spec.description = %q{Provides facilities to utilize UUIDs with ActiveRecord, including model and migration extensions.}
12
+ spec.summary = %q{Provides facilities to utilize UUIDs with ActiveRecord.}
13
+ spec.homepage = "https://github.com/midas/with_uuid"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ #spec.add_development_dependency "database_cleaner"
25
+ #spec.add_development_dependency "forgery"
26
+ #spec.add_development_dependency "fabrication"
27
+ #spec.add_development_dependency "sqlite3"
28
+ #spec.add_development_dependency "pg"
29
+ #spec.add_development_dependency "mysql2"
30
+
31
+ spec.add_runtime_dependency "uuidtools"
32
+ spec.add_runtime_dependency "activerecord", '>= 3.1'
33
+ spec.add_runtime_dependency "activesupport", '>= 3.1'
34
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: with_uuid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Jason Harrelson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: uuidtools
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '3.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '3.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '3.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '3.1'
97
+ description: Provides facilities to utilize UUIDs with ActiveRecord, including model
98
+ and migration extensions.
99
+ email:
100
+ - cjharrelson@iberon.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - .ruby-gemset
107
+ - .ruby-version
108
+ - Gemfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - lib/schema_dumper.rb
113
+ - lib/with_uuid.rb
114
+ - lib/with_uuid/comb_uuid.rb
115
+ - lib/with_uuid/extensions.rb
116
+ - lib/with_uuid/extensions/migrations.rb
117
+ - lib/with_uuid/model.rb
118
+ - lib/with_uuid/railtie.rb
119
+ - lib/with_uuid/version.rb
120
+ - with_uuid.gemspec
121
+ homepage: https://github.com/midas/with_uuid
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.0.5
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Provides facilities to utilize UUIDs with ActiveRecord.
145
+ test_files: []