typed_uuid 2.2 → 4.0.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5bf0c87bdd7950cf4aa85e788d0e4d0ac49ac842947471b2788db6c5e7b347b
4
- data.tar.gz: a396047b9153d11c56ba87412ac7dbd6a3e17e9ecf701eebf9fef8e4542e9971
3
+ metadata.gz: 956d3f40e94a40968f9e66ae955a0eb4ca0a0d5e7c0a307e846a6bc329970108
4
+ data.tar.gz: 49844d2082da751bc4d36dede69bdd927bb93269a8caadcaee20916a66e56c4f
5
5
  SHA512:
6
- metadata.gz: 7e3fe8ade426da5a52beef42674a737ec22837b5c8d758155ee4f962ed81a054cf0a1e8d36c6122e2f4a6ea14db9c0bc88586351812eb8b859a4eeeb886af621
7
- data.tar.gz: 94434e3ab2d1fbb58a41c8dceb4558cf8a554ce16efd3b94aa9a0d62bde91b267da06804a91079076b1a88407e5cec362250a92146c8ac148ffe56ac0f83ebd2
6
+ metadata.gz: 5e4792f1bf817f6d3edf9b958ce843ddbda5d9fbb1286629a4cd91acdc56581d239e167b1808d580d5139233c1a74cc0aae3f88adc5585542413196735f6c7ea
7
+ data.tar.gz: 143e55145e97eb7dd177d2d2785c03f8267cdad624a40cd52ce628c66194ae155c6d852b564eecdf991399e62c05ae1b48837698f362239aff6e2774a5b9ef1c
data/README.md CHANGED
@@ -7,24 +7,35 @@ a hex representation of 4 bits.
7
7
 
8
8
  `xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`
9
9
 
10
- Where:
11
-
12
10
  - M is 4 bits and is the Version
13
11
  - N is 3 bits and is the Variant of the Version followed a bit
14
12
 
15
- We modify this and use the following structure where the 7th & 8th bytes in the
16
- UUID are enum XORed with the result of XORing bytes 5 & 6 with bytes 9 & 10.
13
+ We modify this and use the following structure where the 9th & 10th bytes in the
14
+ UUID are the enum XORed with the result of XORing bytes 7 & 8 with bytes 11 & 12.
17
15
 
18
- `xxxxxxxx-YYYY-TTTT-ZZZZ-xxxxxxxxxxxx`
16
+ `xxxxxxxx-xxxx-YYYY-TTTT-ZZZZxxxxxxxx`
19
17
 
20
18
  Where:
21
19
 
22
- - TTTT is the Type ENUM 0bNNNN_NNNN_NNNN_NNNN (0 - 65,535) XORed with (YYYY xor ZZZZ)
20
+ - TTTT is the Type ENUM & Version 0bEEEE_EEEE_EEEE_EVVV; XORed with (YYYY xor ZZZZ)
21
+ - The Es are the bits of the 13 bit ENUM supporting 8,192 enums/types (0 - 8,191)
22
+ - The Vs are the bits in the 3 bit version supporting 8 versions (0 - 7)
23
23
  - YYYY bytes XORed with ZZZZ and the Type ENUM to produce the identifying bytes
24
24
  - ZZZZ bytes XORed with YYYY and the Type ENUM to produce the identifying bytes
25
25
 
26
- XORing bytes 5 & 6 with 9 & 10 and XORing again with bytes 5 & 6 of the Typed UUID
27
- will give us back the ENUM of the Type using soley the UUID.
26
+ XORing bytes 7 & 8 with 11 & 12 and XORing again with bytes 9 & 10 of the
27
+ Typed UUID will give us back the ENUM and Version of the Type using soley the UUID.
28
+
29
+ ## Versions
30
+
31
+ As with regular UUID Typed UUIDs come in multiple version. The current versions are:
32
+
33
+ - Version 1: A timebased UUID where the first 64 bits are an unsigned integer
34
+ representing the nanoseconds since epoch. The following 16 bits are
35
+ the UUID type folled by 48 random bits.
36
+
37
+ - Version 4: A random UUID where the first 64 bits are random. The following
38
+ 16 bits are the UUID type folled by another 48 random bits.
28
39
 
29
40
  ## Install
30
41
 
@@ -33,24 +44,28 @@ Add this to your Gemfile:
33
44
  `gem 'typed_uuid'`
34
45
 
35
46
  Once bundled you can add an initializer to Rails to register your types as shown
36
- below. This maps the __table_names__ of the models to an integer between 0 and 255.
47
+ below. This maps the __Model Classes__ to an integer between 0 and 65,535.
37
48
 
38
49
  ```ruby
39
50
  # config/initializers/uuid_types.rb
40
51
 
41
52
  ActiveRecord::Base.register_uuid_types({
42
- listings: 0,
43
- buildings: 65_535
53
+ Listing: 0,
54
+ Address: {enum: 5},
55
+ Building: {enum: 512, version: 1},
56
+ 'Building::SkyScrpaer' => 8_191
44
57
  })
45
58
 
46
59
  # Or:
47
60
 
48
61
  ActiveRecord::Base.register_uuid_types({
49
- 0 => :listings,
50
- 65_535 => :buildings
62
+ 0 => :Listing,
63
+ 512 => :Building,
64
+ 8_191 => 'Building::SkyScrpaer'
51
65
  })
52
66
  ```
53
67
 
68
+
54
69
  ## Usage
55
70
 
56
71
  In your migrations simply replace `id: :uuid` with `id: :typed_uuid` when creating
@@ -64,4 +79,12 @@ class CreateProperties < ActiveRecord::Migration[5.2]
64
79
  end
65
80
  end
66
81
  end
67
- ```
82
+ ```
83
+
84
+ ## STI Models
85
+ When using STI Model Rails will generate the UUID to be inserted. This UUID will
86
+ be calculated of the STI Model class and not the base class.
87
+
88
+ In the migration you can still used `id: :typed_uuid`, this will use the base
89
+ class to calculated the default type for the UUID. You could also set the
90
+ `id` to `:uuid` and the `default` to `false` so when no ID is given it will error.
@@ -1,18 +1,33 @@
1
1
  class AddTypedUuidFunction < ActiveRecord::Migration[6.0]
2
2
  def up
3
- enable_extension 'pgcrypto'
3
+ if connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
4
+ enable_extension 'pgcrypto'
4
5
 
5
- execute <<-SQL
6
- CREATE OR REPLACE FUNCTION typed_uuid(t bytea) RETURNS uuid AS $$
6
+ execute <<-SQL
7
+ CREATE OR REPLACE FUNCTION typed_uuid(enum int, version int default 4)
8
+ RETURNS uuid AS $$
7
9
  DECLARE
8
- bytes bytea := gen_random_bytes(16);
9
- uuid bytea;
10
+ bytes bytea;
11
+ type bytea;
10
12
  BEGIN
11
- bytes := set_byte(bytes, 6, (get_byte(bytes, 4) # get_byte(bytes, 8)) # get_byte(t, 0));
12
- bytes := set_byte(bytes, 7, (get_byte(bytes, 5) # get_byte(bytes, 9)) # get_byte(t, 1));
13
+ IF version = 1 THEN
14
+ bytes := decode(concat(
15
+ to_hex((extract(epoch from clock_timestamp())*1000000000)::bigint),
16
+ encode(gen_random_bytes(8), 'hex')
17
+ ), 'hex');
18
+ ELSE
19
+ bytes := gen_random_bytes(16);
20
+ version := 4;
21
+ END IF;
22
+
23
+ type := decode( lpad(to_hex(((enum << 3) | version)), 4, '0'), 'hex');
24
+ bytes := set_byte(bytes, 8, (get_byte(bytes, 6) # get_byte(bytes, 10)) # get_byte(type, 0));
25
+ bytes := set_byte(bytes, 9, (get_byte(bytes, 7) # get_byte(bytes, 11)) # get_byte(type, 1));
26
+
13
27
  RETURN encode( bytes, 'hex') :: uuid;
14
28
  END;
15
- $$ LANGUAGE plpgsql;
16
- SQL
29
+ $$ LANGUAGE plpgsql;
30
+ SQL
31
+ end
17
32
  end
18
- end
33
+ end
@@ -3,15 +3,48 @@ module TypedUUID
3
3
  autoload :PsqlColumnMethods, 'typed_uuid/psql_column_methods'
4
4
  autoload :PsqlSchemaDumper, 'typed_uuid/psql_schema_dumper'
5
5
 
6
- def self.uuid(enum)
7
- uuid = SecureRandom.random_bytes(16).unpack("NnnnnN")
8
- uuid[2] = (uuid[1] ^ uuid[3]) ^ enum
9
- "%08x-%04x-%04x-%04x-%04x%08x" % uuid
6
+ def self.uuid(enum, version = 4)
7
+ if enum < 0 || enum > 8_191
8
+ raise ArgumentError, "UUID type must be between 0 and 8,191"
9
+ end
10
+
11
+ if version == 1
12
+ timestamp_uuid(enum)
13
+ elsif version == 4
14
+ random_uuid(enum)
15
+ end
16
+ end
17
+
18
+ def self.random_uuid(enum)
19
+ uuid = SecureRandom.random_bytes(16).unpack("nnnnnnnn")
20
+
21
+ uuid[4] = (uuid[3] ^ uuid[5]) ^ ((enum << 3) | 4)
22
+ "%04x%04x-%04x-%04x-%04x-%04x%04x%04x" % uuid
23
+ end
24
+
25
+ def self.timestamp_uuid(enum)
26
+ time = Time.now
27
+ uuid = [time.to_i * 1_000_000_000 + time.nsec].pack('Q>')
28
+ uuid << SecureRandom.random_bytes(8)
29
+
30
+ uuid = uuid.unpack("nnnnnnnn")
31
+ uuid[4] = (uuid[3] ^ uuid[5]) ^ ((enum << 3) | 1)
32
+ "%04x%04x-%04x-%04x-%04x-%04x%04x%04x" % uuid
10
33
  end
11
34
 
12
35
  def self.enum(uuid)
13
36
  uuid = uuid.gsub('-', '')
14
- (uuid[8..11].to_i(16) ^ uuid[16..19].to_i(16)) ^ uuid[12..15].to_i(16)
37
+ ((uuid[12..15].to_i(16) ^ uuid[20..23].to_i(16)) ^ uuid[16..19].to_i(16)) >> 3
38
+ end
39
+
40
+ def self.version(uuid)
41
+ uuid = uuid.gsub('-', '')
42
+ ((uuid[12..15].to_i(16) ^ uuid[20..23].to_i(16)) ^ uuid[16..19].to_i(16)) & 0b0000000000000111
43
+ end
44
+
45
+ def self.timestamp(uuid)
46
+ uuid = uuid.gsub('-', '')
47
+ Time.at(*uuid[0..15].to_i(16).divmod(1_000_000_000), :nsec)
15
48
  end
16
49
  end
17
50
 
@@ -1,79 +1,132 @@
1
+ require 'active_support/concern'
2
+
1
3
  module TypedUUID::ActiveRecord
4
+ extend ActiveSupport::Concern
2
5
 
3
6
  UUID_TYPE_CONFLICT_MESSAGE = \
4
- "You tried to define an UUID type %{int} for \"%{table}\", but " \
7
+ "You tried to define an UUID type %{int} for \"%{class_name}\", but " \
5
8
  " %{int} is already defined as the type for %{other}"
6
-
7
- def self.extended(base) # :nodoc:
8
- base.class_attribute(:defined_uuid_types, instance_writer: false, default: {})
9
- base.class_attribute(:uuid_type_cache, instance_writer: false, default: {})
9
+
10
+ included do
11
+ class_attribute(:defined_uuid_types, instance_writer: false, default: {})
12
+ class_attribute(:class_to_uuid_type_cache, instance_writer: false, default: Hash.new { |hash, klass|
13
+ if type = defined_uuid_types.find { |k, v| v[:class] == klass.name }
14
+ hash[klass] = type[1]
15
+ end
16
+ })
17
+ class_attribute(:uuid_enum_to_class_cache, instance_writer: false, default: {})
10
18
  end
11
19
 
12
- def register_uuid_type(table, int)
13
- if int < 0 || int > 65_535
14
- raise ArgumentError, "UUID type must be between 0 and 65,535"
15
- elsif defined_uuid_types.has_key?(int)
16
- raise ArgumentError, UUID_TYPE_CONFLICT_MESSAGE % {
17
- int: int,
18
- table: table,
19
- other: defined_uuid_types[int]
20
- }
21
- else
22
- defined_uuid_types[int] = table.to_s
20
+ def _create_record
21
+ klass = self.class
22
+ if !klass.descends_from_active_record? && klass.typed?
23
+ pk = klass.primary_key
24
+ write_attribute(pk, klass.typed_uuid) if pk && read_attribute(pk).nil?
23
25
  end
26
+
27
+ super
24
28
  end
25
29
 
26
- def register_uuid_types(mapping)
27
- mapping.each do |k, v|
28
- if k.is_a?(Integer)
29
- register_uuid_type(v, k)
30
+ class_methods do
31
+ def register_uuid_type(class_name, enum_or_options)
32
+ if enum_or_options.is_a?(Hash)
33
+ enum = enum_or_options[:enum]
34
+ version = enum_or_options[:version] || 4
30
35
  else
31
- register_uuid_type(k, v)
36
+ enum = enum_or_options
37
+ version = 4
38
+ end
39
+
40
+ if enum < 0 || enum > 8_191
41
+ raise ArgumentError, "UUID type must be between 0 and 65,535"
42
+ elsif defined_uuid_types.has_key?(enum)
43
+ raise ArgumentError, UUID_TYPE_CONFLICT_MESSAGE % {
44
+ int: enum,
45
+ class_name: class_name,
46
+ other: defined_uuid_types[enum]
47
+ }
48
+ else
49
+ defined_uuid_types[enum] = { class: class_name.to_s, version: version, enum: enum }
32
50
  end
33
51
  end
34
- end
35
-
36
- def typed_uuid
37
- TypedUUID.uuid(uuid_type_from_class(self))
38
- end
39
52
 
40
- def uuid_type_from_table_name(table)
41
- type = defined_uuid_types.key(table.to_s)
42
- if type.nil?
43
- raise ArgumentError, "UUID Type for \"#{table}\" not defined"
53
+ def register_uuid_types(mapping)
54
+ mapping.each do |k, v|
55
+ if k.is_a?(Integer)
56
+ register_uuid_type(v, k)
57
+ else
58
+ register_uuid_type(k, v)
59
+ end
60
+ end
44
61
  end
45
-
46
- type
47
- end
48
62
 
49
- def uuid_type_from_class(klass)
50
- type = defined_uuid_types.key(klass.table_name)
51
- if type.nil?
52
- raise ArgumentError, "UUID Type for \"#{table}\" not defined"
63
+ def typed?
64
+ !!class_to_uuid_type_cache[self.base_class]
53
65
  end
54
66
 
55
- type
56
- end
67
+ def typed_uuid
68
+ TypedUUID.uuid(uuid_enum_from_class(self), uuid_version_from_class(self))
69
+ end
70
+
71
+ def uuid_enum_from_table_name(table)
72
+ uuid_enum_from_class(class_from_table_name(table))
73
+ end
74
+
75
+ def uuid_version_from_table_name(table)
76
+ uuid_version_from_class(class_from_table_name(table))
77
+ end
57
78
 
58
- def class_from_uuid_type(type)
59
- if klass = uuid_type_cache[type]
60
- return klass
61
- else
62
- Rails.application.eager_load! if !Rails.application.config.eager_load
79
+ def uuid_enum_from_class(klass)
80
+ type = class_to_uuid_type_cache[klass]
81
+ if type.nil?
82
+ raise ArgumentError, "UUID Type for \"#{klass.name}\" not defined"
83
+ end
84
+
85
+ type[:enum]
86
+ end
87
+
88
+ def uuid_version_from_class(klass)
89
+ type = class_to_uuid_type_cache[klass]
90
+ if type.nil?
91
+ raise ArgumentError, "UUID Type for \"#{klass.name}\" not defined"
92
+ end
63
93
 
64
- ::ActiveRecord::Base.descendants.select do |klass|
94
+ type[:version]
95
+ end
96
+
97
+ def class_from_uuid_enum(enum)
98
+ if uuid_enum_to_class_cache.has_key?(enum)
99
+ uuid_enum_to_class_cache[enum]
100
+ else
101
+ Rails.application.eager_load! if !Rails.application.config.eager_load
102
+
103
+ ::ActiveRecord::Base.descendants.each do |klass|
104
+ next if klass.table_name.nil?
105
+
106
+ if key = defined_uuid_types.find { |enum, info| info[:class] == klass.name }
107
+ uuid_enum_to_class_cache[key[0]] = klass
108
+ end
109
+ end
110
+
111
+ uuid_enum_to_class_cache[enum]
112
+ end
113
+ end
114
+
115
+ def class_from_table_name(table)
116
+ table = table.to_s
117
+ Rails.application.eager_load! if !Rails.application.config.eager_load
118
+
119
+ ::ActiveRecord::Base.descendants.find do |klass|
65
120
  next unless ( klass.superclass == ::ActiveRecord::Base || klass.superclass.abstract_class? )
66
121
  next if klass.table_name.nil?
67
-
68
- uuid_type_cache[defined_uuid_types.key(klass.table_name)] = klass
122
+
123
+ klass.table_name == table
69
124
  end
70
-
71
- uuid_type_cache[type]
72
125
  end
73
- end
74
126
 
75
- def class_from_uuid(uuid)
76
- class_from_uuid_type(TypedUUID.enum(uuid))
127
+ def class_from_uuid(uuid)
128
+ class_from_uuid_enum(TypedUUID.enum(uuid))
129
+ end
77
130
  end
78
131
 
79
132
  end
@@ -2,9 +2,10 @@ module TypedUUID::PsqlColumnMethods
2
2
 
3
3
  def primary_key(name, type = :primary_key, **options)
4
4
  if type == :typed_uuid
5
- klass_enum = ::ActiveRecord::Base.uuid_type_from_table_name(self.name)
5
+ klass_type_enum = ::ActiveRecord::Base.uuid_enum_from_table_name(self.name)
6
+ klass_type_version = ::ActiveRecord::Base.uuid_version_from_table_name(self.name)
6
7
  options[:id] = :uuid
7
- options[:default] ||= -> { "typed_uuid('\\x#{klass_enum.to_s(16).ljust(4, '0')}')" }
8
+ options[:default] ||= -> { "typed_uuid(#{klass_type_enum}, #{klass_type_version})" }
8
9
  super(name, :uuid, **options)
9
10
  else
10
11
  super
@@ -4,7 +4,7 @@ class TypedUUID::Railtie < Rails::Railtie
4
4
  ActiveRecord::Tasks::DatabaseTasks.migrations_paths << File.expand_path('../../../db/migrate', __FILE__)
5
5
 
6
6
  ActiveSupport.on_load(:active_record) do
7
- ActiveRecord::Base.extend TypedUUID::ActiveRecord
7
+ ActiveRecord::Base.include TypedUUID::ActiveRecord
8
8
  end
9
9
 
10
10
  require 'active_record/connection_adapters/postgresql/schema_definitions'
@@ -1,3 +1,3 @@
1
1
  module TypedUUID
2
- VERSION = '2.2'
2
+ VERSION = '4.0.rc1'
3
3
  end
@@ -52,6 +52,10 @@ class ActiveSupport::TestCase
52
52
  set_callback(:setup, :before) do
53
53
  Rails.stubs(:application).returns(stub(config: stub(eager_load: true)))
54
54
  if !self.class.class_variable_defined?(:@@suite_setup_run)
55
+ ActiveRecord::Base.defined_uuid_types.clear
56
+ ActiveRecord::Base.uuid_enum_to_class_cache.clear
57
+ ActiveRecord::Base.class_to_uuid_type_cache.clear
58
+
55
59
  configuration = {
56
60
  adapter: "postgresql",
57
61
  database: "uuid-types-test",
@@ -76,14 +80,14 @@ class ActiveSupport::TestCase
76
80
  self.class.class_variable_set(:@@suite_setup_run, true)
77
81
  end
78
82
 
79
- # def debug
80
- # ActiveRecord::Base.logger = Logger.new(STDOUT)
81
- # $debugging = true
82
- # yield
83
- # ensure
84
- # ActiveRecord::Base.logger = nil
85
- # $debugging = false
86
- # end
83
+ def debug
84
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
85
+ $debugging = true
86
+ yield
87
+ ensure
88
+ ActiveRecord::Base.logger = nil
89
+ $debugging = false
90
+ end
87
91
 
88
92
  def capture_sql
89
93
  # ActiveRecord::Base.connection.materialize_transactions
@@ -4,8 +4,9 @@ class FilterTest < ActiveSupport::TestCase
4
4
 
5
5
  schema do
6
6
  ActiveRecord::Base.register_uuid_types({
7
- listings: 0,
8
- buildings: 65_535
7
+ 'FilterTest::Listing' => {enum: 0, version: 1},
8
+ 'FilterTest::Building' => 592,
9
+ 'FilterTest::SkyScraper' => {enum: 1_952}
9
10
  })
10
11
 
11
12
  create_table :listings, id: :typed_uuid do |t|
@@ -14,6 +15,7 @@ class FilterTest < ActiveSupport::TestCase
14
15
 
15
16
  create_table :buildings, id: :typed_uuid do |t|
16
17
  t.string "name", limit: 255
18
+ t.string "type", limit: 255
17
19
  end
18
20
  end
19
21
 
@@ -22,14 +24,26 @@ class FilterTest < ActiveSupport::TestCase
22
24
 
23
25
  class Building < ActiveRecord::Base
24
26
  end
27
+
28
+ class SkyScraper < Building
29
+ end
25
30
 
31
+ class SingleFamilyHome < Building
32
+ end
33
+
34
+ class Property < ActiveRecord::Base
35
+ end
36
+
37
+ class Lot < ActiveRecord::Base
38
+ end
39
+
26
40
  test 'adding primary key as a typed_uuid in a migration' do
27
41
  ActiveRecord::Base.register_uuid_types({
28
- properties: 1
42
+ 1 => 'FilterTest::Property'
29
43
  })
30
44
 
31
45
  exprexted_sql = <<-SQL
32
- CREATE TABLE "properties" ("id" uuid DEFAULT typed_uuid('\\x1000') NOT NULL PRIMARY KEY, "name" character varying(255))
46
+ CREATE TABLE "properties" ("id" uuid DEFAULT typed_uuid(1, 4) NOT NULL PRIMARY KEY, "name" character varying(255))
33
47
  SQL
34
48
 
35
49
  assert_sql exprexted_sql do
@@ -41,29 +55,100 @@ class FilterTest < ActiveSupport::TestCase
41
55
  end
42
56
  end
43
57
 
58
+ test 'adding primary key as a typed_uuid in a migration with a version' do
59
+ ActiveRecord::Base.register_uuid_types({
60
+ 'FilterTest::Lot' => {version: 1, enum: 512}
61
+ })
62
+
63
+ exprexted_sql = <<-SQL
64
+ CREATE TABLE "lots" ("id" uuid DEFAULT typed_uuid(512, 1) NOT NULL PRIMARY KEY, "name" character varying(255))
65
+ SQL
66
+
67
+ assert_sql exprexted_sql do
68
+ ActiveRecord::Migration.suppress_messages do
69
+ ActiveRecord::Migration.create_table :lots, id: :typed_uuid do |t|
70
+ t.string "name", limit: 255
71
+ end
72
+ end
73
+ end
74
+ end
75
+
44
76
  test 'typed_uuid' do
45
77
  assert_equal 512, TypedUUID.enum(TypedUUID.uuid(512))
46
- assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid(Listing.typed_uuid)
47
- assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid(Building.typed_uuid)
78
+ assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid(Listing.typed_uuid)
79
+ assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid(Building.typed_uuid)
80
+ assert_equal FilterTest::SkyScraper, ::ActiveRecord::Base.class_from_uuid(SkyScraper.typed_uuid)
81
+
82
+ assert_raises ArgumentError do
83
+ ::ActiveRecord::Base.class_from_uuid(SingleFamilyHome.typed_uuid)
84
+ end
48
85
  end
49
86
 
50
- test 'class_from uuid' do
87
+ test 'typed_uuid v1' do
88
+ time = Time.at(1606612254, 370979123, :nsec)
89
+ Time.stubs(:now).returns(time)
90
+
91
+ uuid = TypedUUID.uuid(592, 1)
92
+
93
+ assert_equal 1, TypedUUID.version(uuid)
94
+ assert_equal 592, TypedUUID.enum(uuid)
95
+
96
+ assert_equal time, TypedUUID.timestamp(uuid)
97
+ assert_equal time.to_i, TypedUUID.timestamp(uuid).to_i
98
+ assert_equal time.nsec, TypedUUID.timestamp(uuid).nsec
99
+
100
+ assert_equal Listing, ::ActiveRecord::Base.class_from_uuid(Listing.typed_uuid)
101
+ end
102
+
103
+ test 'class_from uuid generated bye PostgresQL' do
51
104
  listing = Listing.create
52
105
  building = Building.create
106
+ skyscraper = SkyScraper.create
53
107
 
54
108
  assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid(listing.id)
55
109
  assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid(building.id)
110
+ assert_equal FilterTest::SkyScraper, ::ActiveRecord::Base.class_from_uuid(skyscraper.id)
111
+
112
+ assert_raises ArgumentError do
113
+ SingleFamilyHome.create
114
+ end
56
115
  end
57
116
 
58
- test 'uuid_type from table_name' do
59
- assert_equal 0, ::ActiveRecord::Base.uuid_type_from_table_name(:listings)
60
- assert_equal 0, ::ActiveRecord::Base.uuid_type_from_table_name('listings')
61
- assert_equal 65_535, ::ActiveRecord::Base.uuid_type_from_table_name(:buildings)
117
+ test 'class_from v1 uuid generated bye PostgresQL' do
118
+ listing = Listing.create
119
+
120
+ assert_equal Listing, ::ActiveRecord::Base.class_from_uuid(listing.id)
121
+ end
122
+
123
+ test 'uuid_enum from table_name' do
124
+ assert_equal 0, ::ActiveRecord::Base.uuid_enum_from_table_name(:listings)
125
+ assert_equal 0, ::ActiveRecord::Base.uuid_enum_from_table_name('listings')
126
+
127
+ assert_equal 592, ::ActiveRecord::Base.uuid_enum_from_table_name(:buildings)
128
+ end
129
+
130
+ test 'uuid_version from table_name' do
131
+ assert_equal 1, ::ActiveRecord::Base.uuid_version_from_table_name(:listings)
132
+ assert_equal 1, ::ActiveRecord::Base.uuid_version_from_table_name('listings')
133
+ assert_equal 4, ::ActiveRecord::Base.uuid_version_from_table_name(:buildings)
134
+ end
135
+
136
+ test 'uuid_enum from class' do
137
+ assert_equal 0, ::ActiveRecord::Base.uuid_enum_from_class(Listing)
138
+ assert_equal 592, ::ActiveRecord::Base.uuid_enum_from_class(Building)
139
+ assert_equal 1_952, ::ActiveRecord::Base.uuid_enum_from_class(SkyScraper)
140
+ end
141
+
142
+ test 'uuid_version from class' do
143
+ assert_equal 1, ::ActiveRecord::Base.uuid_version_from_class(Listing)
144
+ assert_equal 4, ::ActiveRecord::Base.uuid_version_from_class(Building)
145
+ assert_equal 4, ::ActiveRecord::Base.uuid_version_from_class(SkyScraper)
62
146
  end
63
147
 
64
- test 'class from uuid_type' do
65
- assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid_type(0)
66
- assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid_type(65_535)
148
+ test 'class from uuid_enum' do
149
+ assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid_enum(0)
150
+ assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid_enum(592)
151
+ assert_equal FilterTest::SkyScraper, ::ActiveRecord::Base.class_from_uuid_enum(1_952)
67
152
  end
68
153
 
69
154
  end
@@ -24,8 +24,8 @@ Gem::Specification.new do |s|
24
24
  s.add_development_dependency 'byebug'
25
25
  s.add_development_dependency 'activesupport', '>= 6.0.0'
26
26
  s.add_development_dependency 'rails', '>= 6.0.0'
27
+ s.add_development_dependency 'pg'
27
28
 
28
29
  # Runtime
29
- s.add_runtime_dependency 'pg'
30
30
  s.add_runtime_dependency 'activerecord', '>= 6.0.0'
31
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typed_uuid
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.2'
4
+ version: 4.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-25 00:00:00.000000000 Z
11
+ date: 2020-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -143,7 +143,7 @@ dependencies:
143
143
  - - ">="
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
- type: :runtime
146
+ type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
@@ -190,7 +190,7 @@ files:
190
190
  homepage: https://github.com/malomalo/typed_uuid
191
191
  licenses: []
192
192
  metadata: {}
193
- post_install_message:
193
+ post_install_message:
194
194
  rdoc_options: []
195
195
  require_paths:
196
196
  - lib
@@ -201,12 +201,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
201
201
  version: '0'
202
202
  required_rubygems_version: !ruby/object:Gem::Requirement
203
203
  requirements:
204
- - - ">="
204
+ - - ">"
205
205
  - !ruby/object:Gem::Version
206
- version: '0'
206
+ version: 1.3.1
207
207
  requirements: []
208
- rubygems_version: 3.0.3
209
- signing_key:
208
+ rubygems_version: 3.1.4
209
+ signing_key:
210
210
  specification_version: 4
211
211
  summary: Typed UUIDs for ActiveRecord
212
212
  test_files: