typed_uuid 3.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: c9b97eecee8303b2863faf3982c4080d347c9dabc4b0fca45c2c5dc7c74b6172
4
- data.tar.gz: 72d70bc0bc247987141c6ee4710a5ef34257693179b1d526dcc6fbf427e414f5
3
+ metadata.gz: 956d3f40e94a40968f9e66ae955a0eb4ca0a0d5e7c0a307e846a6bc329970108
4
+ data.tar.gz: 49844d2082da751bc4d36dede69bdd927bb93269a8caadcaee20916a66e56c4f
5
5
  SHA512:
6
- metadata.gz: 204697bd0dc2c7dd64b62dc7b7955cb5d83242c5966bc447c84d79d343f3b0825cc8bd1bb450525a3acc3405a61a1740b06f127a9df6f5f5830f9a063a75f18a
7
- data.tar.gz: cba9d2425930e678e4c44bfc163392fb749c249f5e2930b62998f22fae5ad10cdaa9e8df5df013b6155eac8c1c242056e4ff67b65dfb63140f82f545b24d38d4
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
 
@@ -40,8 +51,9 @@ below. This maps the __Model Classes__ to an integer between 0 and 65,535.
40
51
 
41
52
  ActiveRecord::Base.register_uuid_types({
42
53
  Listing: 0,
43
- Building: 512,
44
- 'Building::SkyScrpaer' => 65_535
54
+ Address: {enum: 5},
55
+ Building: {enum: 512, version: 1},
56
+ 'Building::SkyScrpaer' => 8_191
45
57
  })
46
58
 
47
59
  # Or:
@@ -49,7 +61,7 @@ ActiveRecord::Base.register_uuid_types({
49
61
  ActiveRecord::Base.register_uuid_types({
50
62
  0 => :Listing,
51
63
  512 => :Building,
52
- 65_535 => 'Building::SkyScrpaer'
64
+ 8_191 => 'Building::SkyScrpaer'
53
65
  })
54
66
  ```
55
67
 
@@ -4,15 +4,28 @@ class AddTypedUuidFunction < ActiveRecord::Migration[6.0]
4
4
  enable_extension 'pgcrypto'
5
5
 
6
6
  execute <<-SQL
7
- CREATE OR REPLACE FUNCTION typed_uuid(t bytea) RETURNS uuid AS $$
8
- DECLARE
9
- bytes bytea := gen_random_bytes(16);
10
- uuid bytea;
11
- BEGIN
12
- bytes := set_byte(bytes, 6, (get_byte(bytes, 4) # get_byte(bytes, 8)) # get_byte(t, 0));
13
- bytes := set_byte(bytes, 7, (get_byte(bytes, 5) # get_byte(bytes, 9)) # get_byte(t, 1));
14
- RETURN encode( bytes, 'hex') :: uuid;
15
- END;
7
+ CREATE OR REPLACE FUNCTION typed_uuid(enum int, version int default 4)
8
+ RETURNS uuid AS $$
9
+ DECLARE
10
+ bytes bytea;
11
+ type bytea;
12
+ BEGIN
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
+
27
+ RETURN encode( bytes, 'hex') :: uuid;
28
+ END;
16
29
  $$ LANGUAGE plpgsql;
17
30
  SQL
18
31
  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
 
@@ -10,9 +10,11 @@ module TypedUUID::ActiveRecord
10
10
  included do
11
11
  class_attribute(:defined_uuid_types, instance_writer: false, default: {})
12
12
  class_attribute(:class_to_uuid_type_cache, instance_writer: false, default: Hash.new { |hash, klass|
13
- hash[klass] = defined_uuid_types.key(klass.name)
13
+ if type = defined_uuid_types.find { |k, v| v[:class] == klass.name }
14
+ hash[klass] = type[1]
15
+ end
14
16
  })
15
- class_attribute(:uuid_type_to_class_cache, instance_writer: false, default: {})
17
+ class_attribute(:uuid_enum_to_class_cache, instance_writer: false, default: {})
16
18
  end
17
19
 
18
20
  def _create_record
@@ -26,17 +28,25 @@ module TypedUUID::ActiveRecord
26
28
  end
27
29
 
28
30
  class_methods do
29
- def register_uuid_type(class_name, int)
30
- if int < 0 || int > 65_535
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
35
+ else
36
+ enum = enum_or_options
37
+ version = 4
38
+ end
39
+
40
+ if enum < 0 || enum > 8_191
31
41
  raise ArgumentError, "UUID type must be between 0 and 65,535"
32
- elsif defined_uuid_types.has_key?(int)
42
+ elsif defined_uuid_types.has_key?(enum)
33
43
  raise ArgumentError, UUID_TYPE_CONFLICT_MESSAGE % {
34
- int: int,
44
+ int: enum,
35
45
  class_name: class_name,
36
- other: defined_uuid_types[int]
46
+ other: defined_uuid_types[enum]
37
47
  }
38
48
  else
39
- defined_uuid_types[int] = class_name.to_s
49
+ defined_uuid_types[enum] = { class: class_name.to_s, version: version, enum: enum }
40
50
  end
41
51
  end
42
52
 
@@ -55,36 +65,50 @@ module TypedUUID::ActiveRecord
55
65
  end
56
66
 
57
67
  def typed_uuid
58
- TypedUUID.uuid(uuid_type_from_class(self))
68
+ TypedUUID.uuid(uuid_enum_from_class(self), uuid_version_from_class(self))
59
69
  end
60
-
61
- def uuid_type_from_table_name(table)
62
- uuid_type_from_class(class_from_table_name(table))
70
+
71
+ def uuid_enum_from_table_name(table)
72
+ uuid_enum_from_class(class_from_table_name(table))
63
73
  end
64
74
 
65
- def uuid_type_from_class(klass)
75
+ def uuid_version_from_table_name(table)
76
+ uuid_version_from_class(class_from_table_name(table))
77
+ end
78
+
79
+ def uuid_enum_from_class(klass)
66
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
67
87
 
88
+ def uuid_version_from_class(klass)
89
+ type = class_to_uuid_type_cache[klass]
68
90
  if type.nil?
69
91
  raise ArgumentError, "UUID Type for \"#{klass.name}\" not defined"
70
92
  end
71
93
 
72
- type
94
+ type[:version]
73
95
  end
74
-
75
- def class_from_uuid_type(type)
76
- klass = if uuid_type_to_class_cache.has_key?(type)
77
- uuid_type_to_class_cache[type]
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]
78
100
  else
79
101
  Rails.application.eager_load! if !Rails.application.config.eager_load
80
102
 
81
103
  ::ActiveRecord::Base.descendants.each do |klass|
82
104
  next if klass.table_name.nil?
83
-
84
- uuid_type_to_class_cache[defined_uuid_types.key(klass.name)] = klass
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
85
109
  end
86
110
 
87
- uuid_type_to_class_cache[type]
111
+ uuid_enum_to_class_cache[enum]
88
112
  end
89
113
  end
90
114
 
@@ -101,7 +125,7 @@ module TypedUUID::ActiveRecord
101
125
  end
102
126
 
103
127
  def class_from_uuid(uuid)
104
- class_from_uuid_type(TypedUUID.enum(uuid))
128
+ class_from_uuid_enum(TypedUUID.enum(uuid))
105
129
  end
106
130
  end
107
131
 
@@ -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).rjust(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
@@ -1,3 +1,3 @@
1
1
  module TypedUUID
2
- VERSION = '3.2'
2
+ VERSION = '4.0.rc1'
3
3
  end
@@ -28,9 +28,7 @@ module ActiveRecord::Tasks::DatabaseTasks
28
28
  end
29
29
  TypedUUID::Railtie.initializers.each(&:run)
30
30
  Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
31
- def MiniTest.filter_backtrace(bt)
32
- bt
33
- end
31
+
34
32
  class ActiveSupport::TestCase
35
33
 
36
34
  # File 'lib/active_support/testing/declarative.rb'
@@ -55,7 +53,7 @@ class ActiveSupport::TestCase
55
53
  Rails.stubs(:application).returns(stub(config: stub(eager_load: true)))
56
54
  if !self.class.class_variable_defined?(:@@suite_setup_run)
57
55
  ActiveRecord::Base.defined_uuid_types.clear
58
- ActiveRecord::Base.uuid_type_to_class_cache.clear
56
+ ActiveRecord::Base.uuid_enum_to_class_cache.clear
59
57
  ActiveRecord::Base.class_to_uuid_type_cache.clear
60
58
 
61
59
  configuration = {
@@ -4,9 +4,9 @@ class FilterTest < ActiveSupport::TestCase
4
4
 
5
5
  schema do
6
6
  ActiveRecord::Base.register_uuid_types({
7
- 'FilterTest::Listing' => 0,
7
+ 'FilterTest::Listing' => {enum: 0, version: 1},
8
8
  'FilterTest::Building' => 592,
9
- 'FilterTest::SkyScraper' => 1_952
9
+ 'FilterTest::SkyScraper' => {enum: 1_952}
10
10
  })
11
11
 
12
12
  create_table :listings, id: :typed_uuid do |t|
@@ -34,13 +34,16 @@ class FilterTest < ActiveSupport::TestCase
34
34
  class Property < ActiveRecord::Base
35
35
  end
36
36
 
37
+ class Lot < ActiveRecord::Base
38
+ end
39
+
37
40
  test 'adding primary key as a typed_uuid in a migration' do
38
41
  ActiveRecord::Base.register_uuid_types({
39
42
  1 => 'FilterTest::Property'
40
43
  })
41
44
 
42
45
  exprexted_sql = <<-SQL
43
- CREATE TABLE "properties" ("id" uuid DEFAULT typed_uuid('\\x0001') 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))
44
47
  SQL
45
48
 
46
49
  assert_sql exprexted_sql do
@@ -52,6 +55,24 @@ class FilterTest < ActiveSupport::TestCase
52
55
  end
53
56
  end
54
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
+
55
76
  test 'typed_uuid' do
56
77
  assert_equal 512, TypedUUID.enum(TypedUUID.uuid(512))
57
78
  assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid(Listing.typed_uuid)
@@ -63,7 +84,23 @@ class FilterTest < ActiveSupport::TestCase
63
84
  end
64
85
  end
65
86
 
66
- 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
67
104
  listing = Listing.create
68
105
  building = Building.create
69
106
  skyscraper = SkyScraper.create
@@ -77,23 +114,41 @@ class FilterTest < ActiveSupport::TestCase
77
114
  end
78
115
  end
79
116
 
80
- test 'uuid_type from table_name' do
81
- assert_equal 0, ::ActiveRecord::Base.uuid_type_from_table_name(:listings)
82
- assert_equal 0, ::ActiveRecord::Base.uuid_type_from_table_name('listings')
83
- assert_equal 592, ::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)
84
121
  end
85
122
 
86
- test 'uuid_type from class' do
87
- assert_equal 0, ::ActiveRecord::Base.uuid_type_from_class(Listing)
88
- assert_equal 0, ::ActiveRecord::Base.uuid_type_from_class(Listing)
89
- assert_equal 592, ::ActiveRecord::Base.uuid_type_from_class(Building)
90
- assert_equal 1_952, ::ActiveRecord::Base.uuid_type_from_class(SkyScraper)
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)
91
146
  end
92
147
 
93
- test 'class from uuid_type' do
94
- assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid_type(0)
95
- assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid_type(592)
96
- assert_equal FilterTest::SkyScraper, ::ActiveRecord::Base.class_from_uuid_type(1_952)
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)
97
152
  end
98
153
 
99
154
  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: '3.2'
4
+ version: 4.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-04 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
@@ -201,9 +201,9 @@ 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
208
  rubygems_version: 3.1.4
209
209
  signing_key: