typed_uuid 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5c5433e604f5994bc1cb5787813f0948c7b1c5448aa6e78b61e0d5a5dec056bc
4
+ data.tar.gz: f38b7f09d39467074e06c62e7edb28f34b1426b1f089e61b31457d6a79f002dc
5
+ SHA512:
6
+ metadata.gz: d5b2fc14ab95352601cdd86218d0594399f6bf838a3bb097a50996536ba1ac41dc1b44398fc1e342c743854069b8120800a80f1067b16922966c244a31fd0c9c
7
+ data.tar.gz: 561171c47297962e4c0ac880d7515f3fffafabbb07e606f3d551acc080476bab505496994de79296025f179615f868294b1b410a0eda9c96880135980a1805af
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ coverage
2
+ *.gem
3
+ .byebug_history
data/.tm_properties ADDED
@@ -0,0 +1 @@
1
+ exclude = '{$exclude,log,tmp,.tm_properties,coverage}'
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,168 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ typed_uuid (0.1)
5
+ activerecord (>= 6.0.0)
6
+ pg
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actioncable (6.0.2.1)
12
+ actionpack (= 6.0.2.1)
13
+ nio4r (~> 2.0)
14
+ websocket-driver (>= 0.6.1)
15
+ actionmailbox (6.0.2.1)
16
+ actionpack (= 6.0.2.1)
17
+ activejob (= 6.0.2.1)
18
+ activerecord (= 6.0.2.1)
19
+ activestorage (= 6.0.2.1)
20
+ activesupport (= 6.0.2.1)
21
+ mail (>= 2.7.1)
22
+ actionmailer (6.0.2.1)
23
+ actionpack (= 6.0.2.1)
24
+ actionview (= 6.0.2.1)
25
+ activejob (= 6.0.2.1)
26
+ mail (~> 2.5, >= 2.5.4)
27
+ rails-dom-testing (~> 2.0)
28
+ actionpack (6.0.2.1)
29
+ actionview (= 6.0.2.1)
30
+ activesupport (= 6.0.2.1)
31
+ rack (~> 2.0, >= 2.0.8)
32
+ rack-test (>= 0.6.3)
33
+ rails-dom-testing (~> 2.0)
34
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
35
+ actiontext (6.0.2.1)
36
+ actionpack (= 6.0.2.1)
37
+ activerecord (= 6.0.2.1)
38
+ activestorage (= 6.0.2.1)
39
+ activesupport (= 6.0.2.1)
40
+ nokogiri (>= 1.8.5)
41
+ actionview (6.0.2.1)
42
+ activesupport (= 6.0.2.1)
43
+ builder (~> 3.1)
44
+ erubi (~> 1.4)
45
+ rails-dom-testing (~> 2.0)
46
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
47
+ activejob (6.0.2.1)
48
+ activesupport (= 6.0.2.1)
49
+ globalid (>= 0.3.6)
50
+ activemodel (6.0.2.1)
51
+ activesupport (= 6.0.2.1)
52
+ activerecord (6.0.2.1)
53
+ activemodel (= 6.0.2.1)
54
+ activesupport (= 6.0.2.1)
55
+ activestorage (6.0.2.1)
56
+ actionpack (= 6.0.2.1)
57
+ activejob (= 6.0.2.1)
58
+ activerecord (= 6.0.2.1)
59
+ marcel (~> 0.3.1)
60
+ activesupport (6.0.2.1)
61
+ concurrent-ruby (~> 1.0, >= 1.0.2)
62
+ i18n (>= 0.7, < 2)
63
+ minitest (~> 5.1)
64
+ tzinfo (~> 1.1)
65
+ zeitwerk (~> 2.2)
66
+ ansi (1.5.0)
67
+ builder (3.2.4)
68
+ byebug (11.0.1)
69
+ concurrent-ruby (1.1.5)
70
+ crass (1.0.5)
71
+ docile (1.3.2)
72
+ erubi (1.9.0)
73
+ globalid (0.4.2)
74
+ activesupport (>= 4.2.0)
75
+ i18n (1.7.0)
76
+ concurrent-ruby (~> 1.0)
77
+ json (2.3.0)
78
+ loofah (2.4.0)
79
+ crass (~> 1.0.2)
80
+ nokogiri (>= 1.5.9)
81
+ mail (2.7.1)
82
+ mini_mime (>= 0.1.1)
83
+ marcel (0.3.3)
84
+ mimemagic (~> 0.3.2)
85
+ method_source (0.9.2)
86
+ mimemagic (0.3.3)
87
+ mini_mime (1.0.2)
88
+ mini_portile2 (2.4.0)
89
+ minitest (5.13.0)
90
+ minitest-reporters (1.4.2)
91
+ ansi
92
+ builder
93
+ minitest (>= 5.0)
94
+ ruby-progressbar
95
+ mocha (1.11.1)
96
+ nio4r (2.5.2)
97
+ nokogiri (1.10.7)
98
+ mini_portile2 (~> 2.4.0)
99
+ pg (1.1.4)
100
+ rack (2.0.8)
101
+ rack-test (1.1.0)
102
+ rack (>= 1.0, < 3)
103
+ rails (6.0.2.1)
104
+ actioncable (= 6.0.2.1)
105
+ actionmailbox (= 6.0.2.1)
106
+ actionmailer (= 6.0.2.1)
107
+ actionpack (= 6.0.2.1)
108
+ actiontext (= 6.0.2.1)
109
+ actionview (= 6.0.2.1)
110
+ activejob (= 6.0.2.1)
111
+ activemodel (= 6.0.2.1)
112
+ activerecord (= 6.0.2.1)
113
+ activestorage (= 6.0.2.1)
114
+ activesupport (= 6.0.2.1)
115
+ bundler (>= 1.3.0)
116
+ railties (= 6.0.2.1)
117
+ sprockets-rails (>= 2.0.0)
118
+ rails-dom-testing (2.0.3)
119
+ activesupport (>= 4.2.0)
120
+ nokogiri (>= 1.6)
121
+ rails-html-sanitizer (1.3.0)
122
+ loofah (~> 2.3)
123
+ railties (6.0.2.1)
124
+ actionpack (= 6.0.2.1)
125
+ activesupport (= 6.0.2.1)
126
+ method_source
127
+ rake (>= 0.8.7)
128
+ thor (>= 0.20.3, < 2.0)
129
+ rake (13.0.1)
130
+ ruby-progressbar (1.10.1)
131
+ simplecov (0.17.1)
132
+ docile (~> 1.1)
133
+ json (>= 1.8, < 3)
134
+ simplecov-html (~> 0.10.0)
135
+ simplecov-html (0.10.2)
136
+ sprockets (4.0.0)
137
+ concurrent-ruby (~> 1.0)
138
+ rack (> 1, < 3)
139
+ sprockets-rails (3.2.1)
140
+ actionpack (>= 4.0)
141
+ activesupport (>= 4.0)
142
+ sprockets (>= 3.0.0)
143
+ thor (1.0.1)
144
+ thread_safe (0.3.6)
145
+ tzinfo (1.2.5)
146
+ thread_safe (~> 0.1)
147
+ websocket-driver (0.7.1)
148
+ websocket-extensions (>= 0.1.0)
149
+ websocket-extensions (0.1.4)
150
+ zeitwerk (2.2.2)
151
+
152
+ PLATFORMS
153
+ ruby
154
+
155
+ DEPENDENCIES
156
+ activesupport (>= 6.0.0)
157
+ bundler
158
+ byebug
159
+ minitest
160
+ minitest-reporters
161
+ mocha
162
+ rails (>= 6.0.0)
163
+ rake
164
+ simplecov
165
+ typed_uuid!
166
+
167
+ BUNDLED WITH
168
+ 2.0.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Jon Bracy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # TypedUUID
2
+
3
+ A __Typed UUID__ is an UUID with an enum embeded within the UUID.
4
+
5
+ UUIDs are 128bit or 16bytes. The hex format is represented below where x is
6
+ a hex representation of 4 bits.
7
+
8
+ `xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`
9
+
10
+ Where:
11
+
12
+ - M is 4 bits and is the Version
13
+ - N is 3 bits and is the Variant of the Version followed a bit
14
+
15
+ We modify this and use the following structure where the 7th & 8th bytes in the
16
+ UUID are enum XORed with bytes 5 & 6.
17
+
18
+ `xxxxxxxx-YYYY-TTTT-xxxx-xxxxxxxxxxxx`
19
+
20
+ Where:
21
+
22
+ - TTTT is the Class ENUM 0bNNNN_NNNN_NNNN_NNNN (0 - 65,535) XORed with YYYY
23
+ - YYYY are the bytes to be XORed with the Class ENUM to produce the identifying
24
+ bytes
25
+
26
+ XORing bytes 7 & 8 with bytes 5 & 6 of the Typed UUID will give us back the ENUM
27
+ of the Type using soley the UUID.
28
+
29
+ ## Install
30
+
31
+ Add this to your Gemfile:
32
+
33
+ `gem 'typed_uuid'`
34
+
35
+ 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.
37
+
38
+ ```ruby
39
+ # config/initializers/uuid_types.rb
40
+
41
+ ActiveRecord::Base.register_uuid_types({
42
+ listings: 0,
43
+ buildings: 65_535
44
+ })
45
+
46
+ # Or:
47
+
48
+ ActiveRecord::Base.register_uuid_types({
49
+ 0 => :listings,
50
+ 65_535 => :buildings
51
+ })
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ In your migrations simply replace `id: :uuid` with `id: :typed_uuid` when creating
57
+ a table.
58
+
59
+ ```ruby
60
+ class CreateProperties < ActiveRecord::Migration[5.2]
61
+ def change
62
+ create_table :properties, id: :typed_uuid do |t|
63
+ t.string "name", limit: 255
64
+ end
65
+ end
66
+ end
67
+ ```
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/setup'
2
+ require "bundler/gem_tasks"
3
+ Bundler.require(:development)
4
+
5
+ require 'fileutils'
6
+ require "rake/testtask"
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.libs << 'lib' << 'test'
10
+ t.test_files = FileList['test/**/*_test.rb']
11
+ t.warning = true
12
+ # t.verbose = true
13
+ end
@@ -0,0 +1,18 @@
1
+ class AddTypedUuidFunction < ActiveRecord::Migration[6.0]
2
+ def up
3
+ enable_extension 'pgcrypto'
4
+
5
+ execute <<-SQL
6
+ CREATE OR REPLACE FUNCTION typed_uuid(t bytea) RETURNS uuid AS $$
7
+ DECLARE
8
+ bytes bytea := gen_random_bytes(16);
9
+ uuid bytea;
10
+ BEGIN
11
+ bytes := set_byte(bytes, 6, get_byte(bytes, 4) # get_byte(t, 0));
12
+ bytes := set_byte(bytes, 7, get_byte(bytes, 5) # get_byte(t, 1));
13
+ RETURN encode( bytes, 'hex') :: uuid;
14
+ END;
15
+ $$ LANGUAGE plpgsql;
16
+ SQL
17
+ end
18
+ end
@@ -0,0 +1,67 @@
1
+ module TypedUUID::ActiveRecord
2
+
3
+ UUID_TYPE_CONFLICT_MESSAGE = \
4
+ "You tried to define an UUID type %{int} for \"%{table}\", but " \
5
+ " %{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: {})
10
+ end
11
+
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
23
+ end
24
+ end
25
+
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
+ else
31
+ register_uuid_type(k, v)
32
+ end
33
+ end
34
+ end
35
+
36
+ def uuid_type_from_table_name(table)
37
+ type = defined_uuid_types.key(table.to_s)
38
+ if type.nil?
39
+ raise ArgumentError, "UUID Type for \"#{table}\" not defined"
40
+ end
41
+
42
+ type
43
+ end
44
+
45
+ def class_from_uuid_type(type)
46
+ if klass = uuid_type_cache[type]
47
+ return klass
48
+ else
49
+ # Rails.application.eager_load! if !Rails.application.config.eager_load
50
+
51
+ ::ActiveRecord::Base.descendants.select do |klass|
52
+ next unless ( klass.superclass == ::ActiveRecord::Base || klass.superclass.abstract_class? )
53
+ next if klass.table_name.nil?
54
+
55
+ uuid_type_cache[defined_uuid_types.key(klass.table_name)] = klass
56
+ end
57
+
58
+ uuid_type_cache[type]
59
+ end
60
+ end
61
+
62
+ def class_from_uuid(uuid)
63
+ uuid = uuid.gsub('-', '')
64
+ class_from_uuid_type(uuid[8..11].to_i(16) ^ uuid[12..15].to_i(16))
65
+ end
66
+
67
+ end
@@ -0,0 +1,14 @@
1
+ module TypedUUID::PsqlColumnMethods
2
+
3
+ def primary_key(name, type = :primary_key, **options)
4
+ if type == :typed_uuid
5
+ klass_enum = ::ActiveRecord::Base.uuid_type_from_table_name(self.name)
6
+ options[:id] = :uuid
7
+ options[:default] ||= -> { "typed_uuid('\\x#{klass_enum.to_s(16).ljust(4, '0')}')" }
8
+ super(name, :uuid, **options)
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,14 @@
1
+ class TypedUUID::Railtie < Rails::Railtie
2
+
3
+ initializer :typed_uuid do |app|
4
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths << File.expand_path('../../../db/migrate', __FILE__)
5
+
6
+ ActiveSupport.on_load(:active_record) do
7
+ ActiveRecord::Base.extend TypedUUID::ActiveRecord
8
+ end
9
+
10
+ require 'active_record/connection_adapters/postgresql/schema_definitions'
11
+ ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition.include TypedUUID::PsqlColumnMethods
12
+ end
13
+
14
+ end
@@ -0,0 +1,3 @@
1
+ module TypedUUID
2
+ VERSION = '1.0'
3
+ end
data/lib/typed_uuid.rb ADDED
@@ -0,0 +1,6 @@
1
+ module TypedUUID
2
+ autoload :ActiveRecord, 'typed_uuid/active_record'
3
+ autoload :PsqlColumnMethods, 'typed_uuid/psql_column_methods'
4
+ end
5
+
6
+ require 'typed_uuid/railtie' if defined? Rails
@@ -0,0 +1,194 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter %r{^/test/}
4
+ # add_group 'lib', 'sunstone/lib'
5
+ # add_group 'ext', 'sunstone/ext'
6
+ end
7
+
8
+ # To make testing/debugging easier, test within this source tree versus an
9
+ # installed gem
10
+ $LOAD_PATH << File.expand_path('../lib', __FILE__)
11
+
12
+ require 'byebug'
13
+ require "minitest/autorun"
14
+ require 'minitest/unit'
15
+ require 'minitest/reporters'
16
+ require 'mocha/minitest'
17
+ require 'active_support'
18
+ require 'active_record'
19
+ require 'rails'
20
+ require 'typed_uuid'
21
+ require 'typed_uuid/railtie'
22
+ require File.expand_path('../../db/migrate/20191122234546_add_typed_uuid_function', __FILE__)
23
+
24
+ module ActiveRecord::Tasks::DatabaseTasks
25
+ def migrations_paths
26
+ []
27
+ end
28
+ end
29
+ TypedUUID::Railtie.initializers.each(&:run)
30
+ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
31
+
32
+ class ActiveSupport::TestCase
33
+
34
+ # File 'lib/active_support/testing/declarative.rb'
35
+ def self.test(name, &block)
36
+ test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
37
+ defined = method_defined? test_name
38
+ raise "#{test_name} is already defined in #{self}" if defined
39
+ if block_given?
40
+ define_method(test_name, &block)
41
+ else
42
+ define_method(test_name) do
43
+ skip "No implementation provided for #{name}"
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.schema(&block)
49
+ self.class_variable_set(:@@schema, block)
50
+ end
51
+
52
+ set_callback(:setup, :before) do
53
+ if !self.class.class_variable_defined?(:@@suite_setup_run)
54
+ configuration = {
55
+ adapter: "postgresql",
56
+ database: "uuid-types-test",
57
+ encoding: "utf8"
58
+ }.stringify_keys
59
+
60
+ db_tasks = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(configuration)
61
+ db_tasks.purge
62
+
63
+ ActiveRecord::Base.establish_connection(configuration)
64
+ ActiveRecord::Migration.suppress_messages do
65
+ AddTypedUuidFunction.migrate :up
66
+
67
+ if self.class.class_variable_defined?(:@@schema)
68
+ ActiveRecord::Schema.define(&self.class.class_variable_get(:@@schema))
69
+ ActiveRecord::Migration.execute("SELECT c.relname FROM pg_class c WHERE c.relkind = 'S'").each_row do |row|
70
+ ActiveRecord::Migration.execute("ALTER SEQUENCE #{row[0]} RESTART WITH #{rand(50_000)}")
71
+ end
72
+ end
73
+ end
74
+ end
75
+ self.class.class_variable_set(:@@suite_setup_run, true)
76
+ end
77
+
78
+ # def debug
79
+ # ActiveRecord::Base.logger = Logger.new(STDOUT)
80
+ # $debugging = true
81
+ # yield
82
+ # ensure
83
+ # ActiveRecord::Base.logger = nil
84
+ # $debugging = false
85
+ # end
86
+
87
+ def capture_sql
88
+ # ActiveRecord::Base.connection.materialize_transactions
89
+ SQLLogger.clear_log
90
+ yield
91
+ SQLLogger.log_all.dup
92
+ end
93
+
94
+ def assert_sql(*patterns_to_match)
95
+ if patterns_to_match.all? { |s| s.is_a?(String) } && patterns_to_match.size > 1
96
+ assert_equal(*patterns_to_match.take(2).map { |sql| sql.gsub(/( +|\n\s*|\s+)/, ' ').strip })
97
+ else
98
+ begin
99
+ ret_value = nil
100
+ capture_sql { ret_value = yield }
101
+ ret_value
102
+ ensure
103
+ patterns_to_match.map! {|p| p.is_a?(String) ? p.gsub(/( +|\n\s*|\s+)/, ' ').strip : p }
104
+ failed_patterns = []
105
+ patterns_to_match.each do |pattern|
106
+ failed_patterns << pattern unless SQLLogger.log_all.any?{ |sql| pattern === sql.gsub(/( +|\n\s*|\s+)/, ' ').strip }
107
+ end
108
+ assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{SQLLogger.log.size == 0 ? '' : "\nQueries:\n#{SQLLogger.log.join("\n")}"}"
109
+ end
110
+ end
111
+ end
112
+
113
+ def assert_no_sql(*patterns_to_match)
114
+ if patterns_to_match.all? { |s| s.is_a?(String) }
115
+ assert_not_equal(*patterns_to_match.take(2).map { |sql| sql.gsub(/( +|\n\s*|\s+)/, ' ').strip })
116
+ else
117
+ begin
118
+ ret_value = nil
119
+ capture_sql { ret_value = yield }
120
+ ret_value
121
+ ensure
122
+ failed_patterns = []
123
+ patterns_to_match.each do |pattern|
124
+ failed_patterns << pattern unless SQLLogger.log_all.any?{ |sql| pattern === sql }
125
+ end
126
+ assert !failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} found.#{SQLLogger.log.size == 0 ? '' : "\nQueries:\n#{SQLLogger.log.join("\n")}"}"
127
+ end
128
+ end
129
+ end
130
+
131
+ class SQLLogger
132
+ class << self
133
+ attr_accessor :ignored_sql, :log, :log_all
134
+ def clear_log; self.log = []; self.log_all = []; end
135
+ end
136
+
137
+ self.clear_log
138
+
139
+ self.ignored_sql = [/^PRAGMA/i, /^SELECT currval/i, /^SELECT CAST/i, /^SELECT @@IDENTITY/i, /^SELECT @@ROWCOUNT/i, /^SAVEPOINT/i, /^ROLLBACK TO SAVEPOINT/i, /^RELEASE SAVEPOINT/i, /^SHOW max_identifier_length/i, /^BEGIN/i, /^COMMIT/i]
140
+
141
+ # FIXME: this needs to be refactored so specific database can add their own
142
+ # ignored SQL, or better yet, use a different notification for the queries
143
+ # instead examining the SQL content.
144
+ oracle_ignored = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im, /^\s*select .* from all_constraints/im, /^\s*select .* from all_tab_cols/im]
145
+ mysql_ignored = [/^SHOW FULL TABLES/i, /^SHOW FULL FIELDS/, /^SHOW CREATE TABLE /i, /^SHOW VARIABLES /, /^\s*SELECT (?:column_name|table_name)\b.*\bFROM information_schema\.(?:key_column_usage|tables)\b/im]
146
+ postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select tablename\b.*from pg_tables\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i]
147
+ sqlite3_ignored = [/^\s*SELECT name\b.*\bFROM sqlite_master/im, /^\s*SELECT sql\b.*\bFROM sqlite_master/im]
148
+
149
+ [oracle_ignored, mysql_ignored, postgresql_ignored, sqlite3_ignored].each do |db_ignored_sql|
150
+ ignored_sql.concat db_ignored_sql
151
+ end
152
+
153
+ attr_reader :ignore
154
+
155
+ def initialize(ignore = Regexp.union(self.class.ignored_sql))
156
+ @ignore = ignore
157
+ end
158
+
159
+ def call(name, start, finish, message_id, values)
160
+ sql = values[:sql]
161
+
162
+ # FIXME: this seems bad. we should probably have a better way to indicate
163
+ # the query was cached
164
+ return if 'CACHE' == values[:name]
165
+
166
+ self.class.log_all << sql
167
+ unless ignore =~ sql
168
+ # if $debugging
169
+ # puts caller.select { |l| l.starts_with?(File.expand_path('../../lib', __FILE__)) }
170
+ # puts "\n\n"
171
+ # end
172
+ end
173
+ self.class.log << sql unless ignore =~ sql
174
+ end
175
+ end
176
+ ActiveSupport::Notifications.subscribe('sql.active_record', SQLLogger.new)
177
+
178
+ # test/unit backwards compatibility methods
179
+ alias :assert_raise :assert_raises
180
+ alias :assert_not_empty :refute_empty
181
+ alias :assert_not_equal :refute_equal
182
+ alias :assert_not_in_delta :refute_in_delta
183
+ alias :assert_not_in_epsilon :refute_in_epsilon
184
+ alias :assert_not_includes :refute_includes
185
+ alias :assert_not_instance_of :refute_instance_of
186
+ alias :assert_not_kind_of :refute_kind_of
187
+ alias :assert_no_match :refute_match
188
+ alias :assert_not_nil :refute_nil
189
+ alias :assert_not_operator :refute_operator
190
+ alias :assert_not_predicate :refute_predicate
191
+ alias :assert_not_respond_to :refute_respond_to
192
+ alias :assert_not_same :refute_same
193
+
194
+ end
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+
3
+ class FilterTest < ActiveSupport::TestCase
4
+
5
+ schema do
6
+ ActiveRecord::Base.register_uuid_types({
7
+ listings: 0,
8
+ buildings: 65_535
9
+ })
10
+
11
+ create_table :listings, id: :typed_uuid do |t|
12
+ t.string "name", limit: 255
13
+ end
14
+
15
+ create_table :buildings, id: :typed_uuid do |t|
16
+ t.string "name", limit: 255
17
+ end
18
+ end
19
+
20
+ class Listing < ActiveRecord::Base
21
+ end
22
+
23
+ class Building < ActiveRecord::Base
24
+ end
25
+
26
+ test 'adding primary key as a typed_uuid in a migration' do
27
+ ActiveRecord::Base.register_uuid_types({
28
+ properties: 1
29
+ })
30
+
31
+ exprexted_sql = <<-SQL
32
+ CREATE TABLE "properties" ("id" uuid DEFAULT typed_uuid('\\x1000') NOT NULL PRIMARY KEY, "name" character varying(255))
33
+ SQL
34
+
35
+ assert_sql exprexted_sql do
36
+ ActiveRecord::Migration.suppress_messages do
37
+ ActiveRecord::Migration.create_table :properties, id: :typed_uuid do |t|
38
+ t.string "name", limit: 255
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ test 'class_from uuid' do
45
+ listing = Listing.create
46
+ building = Building.create
47
+
48
+ assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid(listing.id)
49
+ assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid(building.id)
50
+ end
51
+
52
+ test 'uuid_type from table_name' do
53
+ assert_equal 0, ::ActiveRecord::Base.uuid_type_from_table_name(:listings)
54
+ assert_equal 0, ::ActiveRecord::Base.uuid_type_from_table_name('listings')
55
+ assert_equal 65_535, ::ActiveRecord::Base.uuid_type_from_table_name(:buildings)
56
+ end
57
+
58
+ test 'class from uuid_type' do
59
+ assert_equal FilterTest::Listing, ::ActiveRecord::Base.class_from_uuid_type(0)
60
+ assert_equal FilterTest::Building, ::ActiveRecord::Base.class_from_uuid_type(65_535)
61
+ end
62
+
63
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path("../lib/typed_uuid/version", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "typed_uuid"
5
+ s.version = TypedUUID::VERSION
6
+ s.authors = ["Jon Bracy"]
7
+ s.email = ["jonbracy@gmail.com"]
8
+ s.homepage = "https://github.com/malomalo/typed_uuid"
9
+ s.summary = %q{Typed UUIDs for ActiveRecord}
10
+ s.description = %q{Typed UUIDs 2 bytes are reserved in the UUID for the class enum}
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.require_paths = ["lib"]
16
+
17
+ # Developoment
18
+ s.add_development_dependency 'rake'
19
+ s.add_development_dependency 'bundler'
20
+ s.add_development_dependency 'minitest'
21
+ s.add_development_dependency 'minitest-reporters'
22
+ s.add_development_dependency 'simplecov'
23
+ s.add_development_dependency 'mocha'
24
+ s.add_development_dependency 'byebug'
25
+ s.add_development_dependency 'activesupport', '>= 6.0.0'
26
+ s.add_development_dependency 'rails', '>= 6.0.0'
27
+
28
+ # Runtime
29
+ s.add_runtime_dependency 'pg'
30
+ s.add_runtime_dependency 'activerecord', '>= 6.0.0'
31
+ end
metadata ADDED
@@ -0,0 +1,214 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: typed_uuid
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Jon Bracy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
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: minitest
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: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
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: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: activesupport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 6.0.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 6.0.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 6.0.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 6.0.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: pg
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: activerecord
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: 6.0.0
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 6.0.0
167
+ description: Typed UUIDs 2 bytes are reserved in the UUID for the class enum
168
+ email:
169
+ - jonbracy@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".gitignore"
175
+ - ".tm_properties"
176
+ - Gemfile
177
+ - Gemfile.lock
178
+ - LICENSE
179
+ - README.md
180
+ - Rakefile
181
+ - db/migrate/20191222234546_add_typed_uuid_function.rb
182
+ - lib/typed_uuid.rb
183
+ - lib/typed_uuid/active_record.rb
184
+ - lib/typed_uuid/psql_column_methods.rb
185
+ - lib/typed_uuid/railtie.rb
186
+ - lib/typed_uuid/version.rb
187
+ - test/test_helper.rb
188
+ - test/typed_uuid_test.rb
189
+ - typed_uuid.gemspec
190
+ homepage: https://github.com/malomalo/typed_uuid
191
+ licenses: []
192
+ metadata: {}
193
+ post_install_message:
194
+ rdoc_options: []
195
+ require_paths:
196
+ - lib
197
+ required_ruby_version: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ required_rubygems_version: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ requirements: []
208
+ rubygems_version: 3.0.3
209
+ signing_key:
210
+ specification_version: 4
211
+ summary: Typed UUIDs for ActiveRecord
212
+ test_files:
213
+ - test/test_helper.rb
214
+ - test/typed_uuid_test.rb