pg_types 0.2.1

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: e20908d841705a0d9aff62529d44d0b12d0490d51b254c49424601ddd01aa6ce
4
+ data.tar.gz: 0aef0b9dd97da00bd122395c039c3e82a6ad25606abaf76fe903c13dade199d5
5
+ SHA512:
6
+ metadata.gz: b19210b13c1c77c22daf9a321be40e41ebbde543958d4c0cef1f8cebc1c109712744c26dae3b03de383a9945c2ffd5da7cdf4efcecec0573a6ede338d29aa2d0
7
+ data.tar.gz: a95652c5c2c07a3fb70314ad9dddd0d62f08716382fd403937daac15b71c242f8eee06cedcd481d66e7d74935272eb33a5dbebfc752b064eb5350686b8a9387e
data/Appraisals ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise "rails-6.1" do
4
+ gem "activerecord", "~> 6.1.0"
5
+ gem "railties", "~> 6.1.0"
6
+ end
7
+
8
+ appraise "rails-7.0" do
9
+ gem "activerecord", "~> 7.0.0"
10
+ gem "railties", "~> 7.0.0"
11
+ end
12
+
13
+ appraise "rails-7.1" do
14
+ gem "activerecord", "~> 7.1.0"
15
+ gem "railties", "~> 7.1.0"
16
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-11-04
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 mhenrixon
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # PgTypes
2
+
3
+ PgTypes provides Rails integration for managing PostgreSQL custom types (composite types, enums, domains). It allows you to version your custom types and handle them through migrations, similar to how you manage database schema changes, while maintaining a clean `schema.rb` file.
4
+
5
+ ## Features
6
+
7
+ - Versioned PostgreSQL types
8
+ - Rails generator for creating new types
9
+ - Migration support for adding/removing types
10
+ - Proper schema.rb dumping (no need for structure.sql)
11
+ - Support for multiple PostgreSQL versions
12
+ - Support for composite types, enums, and domains
13
+ - Dependencies tracking and proper ordering
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'pg_types'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ ```bash
26
+ $ bundle install
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Creating a New Type
32
+
33
+ Generate a new type:
34
+
35
+ ```bash
36
+ # Create a simple type
37
+ $ rails generate pg:type contact_info
38
+
39
+ # Create a type with fields
40
+ $ rails generate pg:type contact_info --fields email:text phone:varchar active:boolean
41
+
42
+ # Create a specific version
43
+ $ rails generate pg:type contact_info --version 2
44
+ ```
45
+
46
+ This will create:
47
+ - A SQL file in `db/types/contact_info_v1.sql`
48
+ - A migration file to create the type
49
+
50
+ ### SQL Definition
51
+
52
+ Edit the generated SQL file (`db/types/contact_info_v1.sql`):
53
+
54
+ ```sql
55
+ CREATE TYPE contact_info AS (
56
+ email text,
57
+ phone varchar,
58
+ active boolean
59
+ );
60
+ ```
61
+
62
+ For an enum type:
63
+
64
+ ```sql
65
+ CREATE TYPE status AS ENUM (
66
+ 'active',
67
+ 'pending',
68
+ 'inactive'
69
+ );
70
+ ```
71
+
72
+ For a domain type:
73
+
74
+ ```sql
75
+ CREATE DOMAIN positive_integer AS integer
76
+ CHECK (VALUE > 0);
77
+ ```
78
+
79
+ ### Migrations
80
+
81
+ The generated migration will look like:
82
+
83
+ ```ruby
84
+ class CreateTypeContactInfo < ActiveRecord::Migration[7.0]
85
+ def change
86
+ create_type "contact_info", version: 1
87
+ end
88
+ end
89
+ ```
90
+
91
+ You can also create types inline:
92
+
93
+ ```ruby
94
+ class CreateTypeUserStatus < ActiveRecord::Migration[7.0]
95
+ def change
96
+ create_type "user_status", sql_definition: <<-SQL
97
+ CREATE TYPE user_status AS ENUM (
98
+ 'active',
99
+ 'pending',
100
+ 'inactive'
101
+ );
102
+ SQL
103
+ end
104
+ end
105
+ ```
106
+
107
+ ### Managing Versions
108
+
109
+ When you need to update a type, create a new version:
110
+
111
+ 1. Generate a new version:
112
+ ```bash
113
+ $ rails generate pg:type contact_info --version 2 --fields email:text phone:varchar active:boolean preferences:jsonb
114
+ ```
115
+
116
+ 2. Update the SQL in `db/types/contact_info_v2.sql`
117
+
118
+ 3. Create a migration to update to the new version:
119
+ ```ruby
120
+ class UpdateTypeContactInfo < ActiveRecord::Migration[7.0]
121
+ def change
122
+ drop_type "contact_info", force: true # Use force: true if the type is used in tables
123
+ create_type "contact_info", version: 2
124
+ end
125
+ end
126
+ ```
127
+
128
+ ### Using Types in Your Models
129
+
130
+ After creating your types, you can use them in your models:
131
+
132
+ ```ruby
133
+ # For composite types
134
+ class User < ApplicationRecord
135
+ attribute :contact_info, :contact_info # Requires additional setup with ActiveRecord
136
+ end
137
+
138
+ # For enum types
139
+ class User < ApplicationRecord
140
+ enum status: {
141
+ active: 'active',
142
+ pending: 'pending',
143
+ inactive: 'inactive'
144
+ }, _prefix: true
145
+ end
146
+ ```
147
+
148
+ ## Development
149
+
150
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
151
+
152
+ To run tests against multiple Rails versions:
153
+
154
+ ```bash
155
+ bundle exec appraisal install
156
+ bundle exec appraisal rake spec
157
+ ```
158
+
159
+ ## Contributing
160
+
161
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mhenrixon/pg_types. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/mhenrixon/pg_types/blob/main/CODE_OF_CONDUCT.md).
162
+
163
+ ## License
164
+
165
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
166
+
167
+ ## Code of Conduct
168
+
169
+ Everyone interacting in the PgTypes project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mhenrixon/pg_types/blob/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by Appraisal
4
+
5
+ source "https://rubygems.org"
6
+
7
+ gem "activerecord", "~> 6.1.0"
8
+ gem "ammeter"
9
+ gem "appraisal"
10
+ gem "base64"
11
+ gem "bigdecimal"
12
+ gem "database_cleaner"
13
+ gem "drb"
14
+ gem "gem-release"
15
+ gem "logger"
16
+ gem "mutex_m"
17
+ gem "railties", "~> 6.1.0"
18
+ gem "rake"
19
+ gem "rspec"
20
+ gem "rubocop-mhenrixon"
21
+ gem "rubocop-rake"
22
+ gem "rubocop-rspec"
23
+
24
+ gemspec path: "../"
@@ -0,0 +1,176 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ pg_types (0.2.0)
5
+ activerecord (>= 6.1)
6
+ pg (>= 1.1)
7
+ railties (>= 6.1)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionpack (6.1.7.10)
13
+ actionview (= 6.1.7.10)
14
+ activesupport (= 6.1.7.10)
15
+ rack (~> 2.0, >= 2.0.9)
16
+ rack-test (>= 0.6.3)
17
+ rails-dom-testing (~> 2.0)
18
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
19
+ actionview (6.1.7.10)
20
+ activesupport (= 6.1.7.10)
21
+ builder (~> 3.1)
22
+ erubi (~> 1.4)
23
+ rails-dom-testing (~> 2.0)
24
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
25
+ activemodel (6.1.7.10)
26
+ activesupport (= 6.1.7.10)
27
+ activerecord (6.1.7.10)
28
+ activemodel (= 6.1.7.10)
29
+ activesupport (= 6.1.7.10)
30
+ activesupport (6.1.7.10)
31
+ concurrent-ruby (~> 1.0, >= 1.0.2)
32
+ i18n (>= 1.6, < 2)
33
+ minitest (>= 5.1)
34
+ tzinfo (~> 2.0)
35
+ zeitwerk (~> 2.3)
36
+ ammeter (1.1.7)
37
+ activesupport (>= 3.0)
38
+ railties (>= 3.0)
39
+ rspec-rails (>= 2.2)
40
+ appraisal (2.5.0)
41
+ bundler
42
+ rake
43
+ thor (>= 0.14.0)
44
+ ast (2.4.2)
45
+ base64 (0.2.0)
46
+ bigdecimal (3.1.8)
47
+ builder (3.3.0)
48
+ concurrent-ruby (1.3.4)
49
+ crass (1.0.6)
50
+ database_cleaner (2.1.0)
51
+ database_cleaner-active_record (>= 2, < 3)
52
+ database_cleaner-active_record (2.2.0)
53
+ activerecord (>= 5.a)
54
+ database_cleaner-core (~> 2.0.0)
55
+ database_cleaner-core (2.0.1)
56
+ diff-lcs (1.5.1)
57
+ drb (2.2.1)
58
+ erubi (1.13.0)
59
+ gem-release (2.2.2)
60
+ i18n (1.14.6)
61
+ concurrent-ruby (~> 1.0)
62
+ json (2.7.6)
63
+ language_server-protocol (3.17.0.3)
64
+ logger (1.6.1)
65
+ loofah (2.23.1)
66
+ crass (~> 1.0.2)
67
+ nokogiri (>= 1.12.0)
68
+ method_source (1.1.0)
69
+ minitest (5.25.1)
70
+ mutex_m (0.2.0)
71
+ nokogiri (1.16.7-arm64-darwin)
72
+ racc (~> 1.4)
73
+ parallel (1.26.3)
74
+ parser (3.3.5.1)
75
+ ast (~> 2.4.1)
76
+ racc
77
+ pg (1.5.9)
78
+ racc (1.8.1)
79
+ rack (2.2.10)
80
+ rack-test (2.1.0)
81
+ rack (>= 1.3)
82
+ rails-dom-testing (2.2.0)
83
+ activesupport (>= 5.0.0)
84
+ minitest
85
+ nokogiri (>= 1.6)
86
+ rails-html-sanitizer (1.6.0)
87
+ loofah (~> 2.21)
88
+ nokogiri (~> 1.14)
89
+ railties (6.1.7.10)
90
+ actionpack (= 6.1.7.10)
91
+ activesupport (= 6.1.7.10)
92
+ method_source
93
+ rake (>= 12.2)
94
+ thor (~> 1.0)
95
+ rainbow (3.1.1)
96
+ rake (13.2.1)
97
+ regexp_parser (2.9.2)
98
+ rspec (3.13.0)
99
+ rspec-core (~> 3.13.0)
100
+ rspec-expectations (~> 3.13.0)
101
+ rspec-mocks (~> 3.13.0)
102
+ rspec-core (3.13.2)
103
+ rspec-support (~> 3.13.0)
104
+ rspec-expectations (3.13.3)
105
+ diff-lcs (>= 1.2.0, < 2.0)
106
+ rspec-support (~> 3.13.0)
107
+ rspec-mocks (3.13.2)
108
+ diff-lcs (>= 1.2.0, < 2.0)
109
+ rspec-support (~> 3.13.0)
110
+ rspec-rails (6.1.5)
111
+ actionpack (>= 6.1)
112
+ activesupport (>= 6.1)
113
+ railties (>= 6.1)
114
+ rspec-core (~> 3.13)
115
+ rspec-expectations (~> 3.13)
116
+ rspec-mocks (~> 3.13)
117
+ rspec-support (~> 3.13)
118
+ rspec-support (3.13.1)
119
+ rubocop (1.68.0)
120
+ json (~> 2.3)
121
+ language_server-protocol (>= 3.17.0)
122
+ parallel (~> 1.10)
123
+ parser (>= 3.3.0.2)
124
+ rainbow (>= 2.2.2, < 4.0)
125
+ regexp_parser (>= 2.4, < 3.0)
126
+ rubocop-ast (>= 1.32.2, < 2.0)
127
+ ruby-progressbar (~> 1.7)
128
+ unicode-display_width (>= 2.4.0, < 3.0)
129
+ rubocop-ast (1.34.0)
130
+ parser (>= 3.3.1.0)
131
+ rubocop-mhenrixon (3.0.0)
132
+ rubocop
133
+ rubocop-performance
134
+ rubocop-rake
135
+ rubocop-rspec
136
+ rubocop-thread_safety
137
+ rubocop-performance (1.22.1)
138
+ rubocop (>= 1.48.1, < 2.0)
139
+ rubocop-ast (>= 1.31.1, < 2.0)
140
+ rubocop-rake (0.6.0)
141
+ rubocop (~> 1.0)
142
+ rubocop-rspec (3.2.0)
143
+ rubocop (~> 1.61)
144
+ rubocop-thread_safety (0.5.1)
145
+ rubocop (>= 0.90.0)
146
+ ruby-progressbar (1.13.0)
147
+ thor (1.3.2)
148
+ tzinfo (2.0.6)
149
+ concurrent-ruby (~> 1.0)
150
+ unicode-display_width (2.6.0)
151
+ zeitwerk (2.7.1)
152
+
153
+ PLATFORMS
154
+ arm64-darwin
155
+
156
+ DEPENDENCIES
157
+ activerecord (~> 6.1.0)
158
+ ammeter
159
+ appraisal
160
+ base64
161
+ bigdecimal
162
+ database_cleaner
163
+ drb
164
+ gem-release
165
+ logger
166
+ mutex_m
167
+ pg_types!
168
+ railties (~> 6.1.0)
169
+ rake
170
+ rspec
171
+ rubocop-mhenrixon
172
+ rubocop-rake
173
+ rubocop-rspec
174
+
175
+ BUNDLED WITH
176
+ 2.5.20
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by Appraisal
4
+
5
+ source "https://rubygems.org"
6
+
7
+ gem "activerecord", "~> 7.0.0"
8
+ gem "ammeter"
9
+ gem "appraisal"
10
+ gem "base64"
11
+ gem "bigdecimal"
12
+ gem "database_cleaner"
13
+ gem "drb"
14
+ gem "gem-release"
15
+ gem "logger"
16
+ gem "mutex_m"
17
+ gem "railties", "~> 7.0.0"
18
+ gem "rake"
19
+ gem "rspec"
20
+ gem "rubocop-mhenrixon"
21
+ gem "rubocop-rake"
22
+ gem "rubocop-rspec"
23
+
24
+ gemspec path: "../"
@@ -0,0 +1,176 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ pg_types (0.2.0)
5
+ activerecord (>= 6.1)
6
+ pg (>= 1.1)
7
+ railties (>= 6.1)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionpack (7.0.8.6)
13
+ actionview (= 7.0.8.6)
14
+ activesupport (= 7.0.8.6)
15
+ rack (~> 2.0, >= 2.2.4)
16
+ rack-test (>= 0.6.3)
17
+ rails-dom-testing (~> 2.0)
18
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
19
+ actionview (7.0.8.6)
20
+ activesupport (= 7.0.8.6)
21
+ builder (~> 3.1)
22
+ erubi (~> 1.4)
23
+ rails-dom-testing (~> 2.0)
24
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
25
+ activemodel (7.0.8.6)
26
+ activesupport (= 7.0.8.6)
27
+ activerecord (7.0.8.6)
28
+ activemodel (= 7.0.8.6)
29
+ activesupport (= 7.0.8.6)
30
+ activesupport (7.0.8.6)
31
+ concurrent-ruby (~> 1.0, >= 1.0.2)
32
+ i18n (>= 1.6, < 2)
33
+ minitest (>= 5.1)
34
+ tzinfo (~> 2.0)
35
+ ammeter (1.1.7)
36
+ activesupport (>= 3.0)
37
+ railties (>= 3.0)
38
+ rspec-rails (>= 2.2)
39
+ appraisal (2.5.0)
40
+ bundler
41
+ rake
42
+ thor (>= 0.14.0)
43
+ ast (2.4.2)
44
+ base64 (0.2.0)
45
+ bigdecimal (3.1.8)
46
+ builder (3.3.0)
47
+ concurrent-ruby (1.3.4)
48
+ crass (1.0.6)
49
+ database_cleaner (2.1.0)
50
+ database_cleaner-active_record (>= 2, < 3)
51
+ database_cleaner-active_record (2.2.0)
52
+ activerecord (>= 5.a)
53
+ database_cleaner-core (~> 2.0.0)
54
+ database_cleaner-core (2.0.1)
55
+ diff-lcs (1.5.1)
56
+ drb (2.2.1)
57
+ erubi (1.13.0)
58
+ gem-release (2.2.2)
59
+ i18n (1.14.6)
60
+ concurrent-ruby (~> 1.0)
61
+ json (2.7.6)
62
+ language_server-protocol (3.17.0.3)
63
+ logger (1.6.1)
64
+ loofah (2.23.1)
65
+ crass (~> 1.0.2)
66
+ nokogiri (>= 1.12.0)
67
+ method_source (1.1.0)
68
+ minitest (5.25.1)
69
+ mutex_m (0.2.0)
70
+ nokogiri (1.16.7-arm64-darwin)
71
+ racc (~> 1.4)
72
+ parallel (1.26.3)
73
+ parser (3.3.5.1)
74
+ ast (~> 2.4.1)
75
+ racc
76
+ pg (1.5.9)
77
+ racc (1.8.1)
78
+ rack (2.2.10)
79
+ rack-test (2.1.0)
80
+ rack (>= 1.3)
81
+ rails-dom-testing (2.2.0)
82
+ activesupport (>= 5.0.0)
83
+ minitest
84
+ nokogiri (>= 1.6)
85
+ rails-html-sanitizer (1.6.0)
86
+ loofah (~> 2.21)
87
+ nokogiri (~> 1.14)
88
+ railties (7.0.8.6)
89
+ actionpack (= 7.0.8.6)
90
+ activesupport (= 7.0.8.6)
91
+ method_source
92
+ rake (>= 12.2)
93
+ thor (~> 1.0)
94
+ zeitwerk (~> 2.5)
95
+ rainbow (3.1.1)
96
+ rake (13.2.1)
97
+ regexp_parser (2.9.2)
98
+ rspec (3.13.0)
99
+ rspec-core (~> 3.13.0)
100
+ rspec-expectations (~> 3.13.0)
101
+ rspec-mocks (~> 3.13.0)
102
+ rspec-core (3.13.2)
103
+ rspec-support (~> 3.13.0)
104
+ rspec-expectations (3.13.3)
105
+ diff-lcs (>= 1.2.0, < 2.0)
106
+ rspec-support (~> 3.13.0)
107
+ rspec-mocks (3.13.2)
108
+ diff-lcs (>= 1.2.0, < 2.0)
109
+ rspec-support (~> 3.13.0)
110
+ rspec-rails (7.0.1)
111
+ actionpack (>= 7.0)
112
+ activesupport (>= 7.0)
113
+ railties (>= 7.0)
114
+ rspec-core (~> 3.13)
115
+ rspec-expectations (~> 3.13)
116
+ rspec-mocks (~> 3.13)
117
+ rspec-support (~> 3.13)
118
+ rspec-support (3.13.1)
119
+ rubocop (1.68.0)
120
+ json (~> 2.3)
121
+ language_server-protocol (>= 3.17.0)
122
+ parallel (~> 1.10)
123
+ parser (>= 3.3.0.2)
124
+ rainbow (>= 2.2.2, < 4.0)
125
+ regexp_parser (>= 2.4, < 3.0)
126
+ rubocop-ast (>= 1.32.2, < 2.0)
127
+ ruby-progressbar (~> 1.7)
128
+ unicode-display_width (>= 2.4.0, < 3.0)
129
+ rubocop-ast (1.34.0)
130
+ parser (>= 3.3.1.0)
131
+ rubocop-mhenrixon (3.0.0)
132
+ rubocop
133
+ rubocop-performance
134
+ rubocop-rake
135
+ rubocop-rspec
136
+ rubocop-thread_safety
137
+ rubocop-performance (1.22.1)
138
+ rubocop (>= 1.48.1, < 2.0)
139
+ rubocop-ast (>= 1.31.1, < 2.0)
140
+ rubocop-rake (0.6.0)
141
+ rubocop (~> 1.0)
142
+ rubocop-rspec (3.2.0)
143
+ rubocop (~> 1.61)
144
+ rubocop-thread_safety (0.5.1)
145
+ rubocop (>= 0.90.0)
146
+ ruby-progressbar (1.13.0)
147
+ thor (1.3.2)
148
+ tzinfo (2.0.6)
149
+ concurrent-ruby (~> 1.0)
150
+ unicode-display_width (2.6.0)
151
+ zeitwerk (2.7.1)
152
+
153
+ PLATFORMS
154
+ arm64-darwin
155
+
156
+ DEPENDENCIES
157
+ activerecord (~> 7.0.0)
158
+ ammeter
159
+ appraisal
160
+ base64
161
+ bigdecimal
162
+ database_cleaner
163
+ drb
164
+ gem-release
165
+ logger
166
+ mutex_m
167
+ pg_types!
168
+ railties (~> 7.0.0)
169
+ rake
170
+ rspec
171
+ rubocop-mhenrixon
172
+ rubocop-rake
173
+ rubocop-rspec
174
+
175
+ BUNDLED WITH
176
+ 2.5.20
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by Appraisal
4
+
5
+ source "https://rubygems.org"
6
+
7
+ gem "activerecord", "~> 7.1.0"
8
+ gem "ammeter"
9
+ gem "appraisal"
10
+ gem "base64"
11
+ gem "bigdecimal"
12
+ gem "database_cleaner"
13
+ gem "drb"
14
+ gem "gem-release"
15
+ gem "logger"
16
+ gem "mutex_m"
17
+ gem "railties", "~> 7.1.0"
18
+ gem "rake"
19
+ gem "rspec"
20
+ gem "rubocop-mhenrixon"
21
+ gem "rubocop-rake"
22
+ gem "rubocop-rspec"
23
+
24
+ gemspec path: "../"
@@ -0,0 +1,207 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ pg_types (0.2.0)
5
+ activerecord (>= 6.1)
6
+ pg (>= 1.1)
7
+ railties (>= 6.1)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionpack (7.1.5)
13
+ actionview (= 7.1.5)
14
+ activesupport (= 7.1.5)
15
+ nokogiri (>= 1.8.5)
16
+ racc
17
+ rack (>= 2.2.4)
18
+ rack-session (>= 1.0.1)
19
+ rack-test (>= 0.6.3)
20
+ rails-dom-testing (~> 2.2)
21
+ rails-html-sanitizer (~> 1.6)
22
+ actionview (7.1.5)
23
+ activesupport (= 7.1.5)
24
+ builder (~> 3.1)
25
+ erubi (~> 1.11)
26
+ rails-dom-testing (~> 2.2)
27
+ rails-html-sanitizer (~> 1.6)
28
+ activemodel (7.1.5)
29
+ activesupport (= 7.1.5)
30
+ activerecord (7.1.5)
31
+ activemodel (= 7.1.5)
32
+ activesupport (= 7.1.5)
33
+ timeout (>= 0.4.0)
34
+ activesupport (7.1.5)
35
+ base64
36
+ benchmark (>= 0.3)
37
+ bigdecimal
38
+ concurrent-ruby (~> 1.0, >= 1.0.2)
39
+ connection_pool (>= 2.2.5)
40
+ drb
41
+ i18n (>= 1.6, < 2)
42
+ logger (>= 1.4.2)
43
+ minitest (>= 5.1)
44
+ mutex_m
45
+ securerandom (>= 0.3)
46
+ tzinfo (~> 2.0)
47
+ ammeter (1.1.7)
48
+ activesupport (>= 3.0)
49
+ railties (>= 3.0)
50
+ rspec-rails (>= 2.2)
51
+ appraisal (2.5.0)
52
+ bundler
53
+ rake
54
+ thor (>= 0.14.0)
55
+ ast (2.4.2)
56
+ base64 (0.2.0)
57
+ benchmark (0.3.0)
58
+ bigdecimal (3.1.8)
59
+ builder (3.3.0)
60
+ concurrent-ruby (1.3.4)
61
+ connection_pool (2.4.1)
62
+ crass (1.0.6)
63
+ database_cleaner (2.1.0)
64
+ database_cleaner-active_record (>= 2, < 3)
65
+ database_cleaner-active_record (2.2.0)
66
+ activerecord (>= 5.a)
67
+ database_cleaner-core (~> 2.0.0)
68
+ database_cleaner-core (2.0.1)
69
+ diff-lcs (1.5.1)
70
+ drb (2.2.1)
71
+ erubi (1.13.0)
72
+ gem-release (2.2.2)
73
+ i18n (1.14.6)
74
+ concurrent-ruby (~> 1.0)
75
+ io-console (0.7.2)
76
+ irb (1.14.1)
77
+ rdoc (>= 4.0.0)
78
+ reline (>= 0.4.2)
79
+ json (2.7.6)
80
+ language_server-protocol (3.17.0.3)
81
+ logger (1.6.1)
82
+ loofah (2.23.1)
83
+ crass (~> 1.0.2)
84
+ nokogiri (>= 1.12.0)
85
+ minitest (5.25.1)
86
+ mutex_m (0.2.0)
87
+ nokogiri (1.16.7-arm64-darwin)
88
+ racc (~> 1.4)
89
+ parallel (1.26.3)
90
+ parser (3.3.5.1)
91
+ ast (~> 2.4.1)
92
+ racc
93
+ pg (1.5.9)
94
+ psych (5.1.2)
95
+ stringio
96
+ racc (1.8.1)
97
+ rack (3.1.8)
98
+ rack-session (2.0.0)
99
+ rack (>= 3.0.0)
100
+ rack-test (2.1.0)
101
+ rack (>= 1.3)
102
+ rackup (2.2.0)
103
+ rack (>= 3)
104
+ rails-dom-testing (2.2.0)
105
+ activesupport (>= 5.0.0)
106
+ minitest
107
+ nokogiri (>= 1.6)
108
+ rails-html-sanitizer (1.6.0)
109
+ loofah (~> 2.21)
110
+ nokogiri (~> 1.14)
111
+ railties (7.1.5)
112
+ actionpack (= 7.1.5)
113
+ activesupport (= 7.1.5)
114
+ irb
115
+ rackup (>= 1.0.0)
116
+ rake (>= 12.2)
117
+ thor (~> 1.0, >= 1.2.2)
118
+ zeitwerk (~> 2.6)
119
+ rainbow (3.1.1)
120
+ rake (13.2.1)
121
+ rdoc (6.7.0)
122
+ psych (>= 4.0.0)
123
+ regexp_parser (2.9.2)
124
+ reline (0.5.10)
125
+ io-console (~> 0.5)
126
+ rspec (3.13.0)
127
+ rspec-core (~> 3.13.0)
128
+ rspec-expectations (~> 3.13.0)
129
+ rspec-mocks (~> 3.13.0)
130
+ rspec-core (3.13.2)
131
+ rspec-support (~> 3.13.0)
132
+ rspec-expectations (3.13.3)
133
+ diff-lcs (>= 1.2.0, < 2.0)
134
+ rspec-support (~> 3.13.0)
135
+ rspec-mocks (3.13.2)
136
+ diff-lcs (>= 1.2.0, < 2.0)
137
+ rspec-support (~> 3.13.0)
138
+ rspec-rails (7.0.1)
139
+ actionpack (>= 7.0)
140
+ activesupport (>= 7.0)
141
+ railties (>= 7.0)
142
+ rspec-core (~> 3.13)
143
+ rspec-expectations (~> 3.13)
144
+ rspec-mocks (~> 3.13)
145
+ rspec-support (~> 3.13)
146
+ rspec-support (3.13.1)
147
+ rubocop (1.68.0)
148
+ json (~> 2.3)
149
+ language_server-protocol (>= 3.17.0)
150
+ parallel (~> 1.10)
151
+ parser (>= 3.3.0.2)
152
+ rainbow (>= 2.2.2, < 4.0)
153
+ regexp_parser (>= 2.4, < 3.0)
154
+ rubocop-ast (>= 1.32.2, < 2.0)
155
+ ruby-progressbar (~> 1.7)
156
+ unicode-display_width (>= 2.4.0, < 3.0)
157
+ rubocop-ast (1.34.0)
158
+ parser (>= 3.3.1.0)
159
+ rubocop-mhenrixon (3.0.0)
160
+ rubocop
161
+ rubocop-performance
162
+ rubocop-rake
163
+ rubocop-rspec
164
+ rubocop-thread_safety
165
+ rubocop-performance (1.22.1)
166
+ rubocop (>= 1.48.1, < 2.0)
167
+ rubocop-ast (>= 1.31.1, < 2.0)
168
+ rubocop-rake (0.6.0)
169
+ rubocop (~> 1.0)
170
+ rubocop-rspec (3.2.0)
171
+ rubocop (~> 1.61)
172
+ rubocop-thread_safety (0.5.1)
173
+ rubocop (>= 0.90.0)
174
+ ruby-progressbar (1.13.0)
175
+ securerandom (0.3.1)
176
+ stringio (3.1.1)
177
+ thor (1.3.2)
178
+ timeout (0.4.1)
179
+ tzinfo (2.0.6)
180
+ concurrent-ruby (~> 1.0)
181
+ unicode-display_width (2.6.0)
182
+ zeitwerk (2.7.1)
183
+
184
+ PLATFORMS
185
+ arm64-darwin
186
+
187
+ DEPENDENCIES
188
+ activerecord (~> 7.1.0)
189
+ ammeter
190
+ appraisal
191
+ base64
192
+ bigdecimal
193
+ database_cleaner
194
+ drb
195
+ gem-release
196
+ logger
197
+ mutex_m
198
+ pg_types!
199
+ railties (~> 7.1.0)
200
+ rake
201
+ rspec
202
+ rubocop-mhenrixon
203
+ rubocop-rake
204
+ rubocop-rspec
205
+
206
+ BUNDLED WITH
207
+ 2.5.20
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module Pg
7
+ module Generators
8
+ class AggregateGenerator < Rails::Generators::NamedBase
9
+ include Rails::Generators::Migration
10
+
11
+ source_root File.expand_path("templates", __dir__)
12
+
13
+ class_option :version,
14
+ type: :string,
15
+ default: "1",
16
+ desc: "Specify a version for the aggregate"
17
+
18
+ def create_aggregate_file
19
+ @version = options[:version]
20
+ @aggregate_name = file_name
21
+
22
+ template(
23
+ "aggregate.sql.erb",
24
+ "db/aggregates/#{file_name}_v#{@version}.sql"
25
+ )
26
+ end
27
+
28
+ def create_migration_file
29
+ @version = options[:version]
30
+ @aggregate_name = file_name
31
+ @migration_version = migration_version
32
+
33
+ migration_template(
34
+ "migration.rb.erb",
35
+ "db/migrate/create_aggregate_#{file_name}.rb"
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def self.next_migration_number(dirname)
42
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
43
+ end
44
+
45
+ def migration_version
46
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ class CreateType<%= @type_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ create_type "<%= @type_name %>", version: <%= @version %>
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ CREATE TYPE <%= @type_name %> AS (
2
+ <% if @fields.any? -%>
3
+ <% @fields.each_with_index do |field, index| -%>
4
+ <%= field[:name] %> <%= field[:type] %><%= index == @fields.length - 1 ? '' : ',' %>
5
+ <% end -%>
6
+ <% else -%>
7
+ value text
8
+ <% end -%>
9
+ );
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module Pg
7
+ module Generators
8
+ class TypeGenerator < Rails::Generators::NamedBase
9
+ include Rails::Generators::Migration
10
+
11
+ source_root File.expand_path("templates", __dir__)
12
+
13
+ class_option :version,
14
+ type: :string,
15
+ default: "1",
16
+ desc: "Specify a version for the type"
17
+
18
+ class_option :fields,
19
+ type: :array,
20
+ default: [],
21
+ desc: "Fields for composite type (e.g. name:text active:boolean)"
22
+
23
+ def create_type_file
24
+ @version = options[:version]
25
+ @type_name = file_name
26
+ @fields = parse_fields(options[:fields])
27
+
28
+ template(
29
+ "type.sql.erb",
30
+ "db/types/#{file_name}_v#{@version}.sql"
31
+ )
32
+ end
33
+
34
+ def create_migration_file
35
+ @version = options[:version]
36
+ @type_name = file_name
37
+ @migration_version = migration_version
38
+
39
+ migration_template(
40
+ "migration.rb.erb",
41
+ "db/migrate/create_type_#{file_name}.rb"
42
+ )
43
+ end
44
+
45
+ private
46
+
47
+ def self.next_migration_number(dirname)
48
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
49
+ end
50
+
51
+ def migration_version
52
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
53
+ end
54
+
55
+ def parse_fields(fields)
56
+ fields.map do |field|
57
+ name, type = field.split(":")
58
+ { name: name, type: type || "text" }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ module CommandRecorder
5
+ def create_type(*args, &block)
6
+ record(:create_type, args, &block)
7
+ end
8
+
9
+ def drop_type(*args)
10
+ record(:drop_type, args)
11
+ end
12
+
13
+ def invert_create_type(args)
14
+ [:drop_type, [args.first]]
15
+ end
16
+
17
+ def invert_drop_type(args)
18
+ # When inverting a drop_type, we need the version from the original file
19
+ type_name = args.first
20
+ version = find_latest_version(type_name)
21
+
22
+ [:create_type, [type_name, { version: version }]]
23
+ end
24
+
25
+ private
26
+
27
+ def find_latest_version(type_name)
28
+ files = Dir[Rails.root.join("db/types/#{type_name}_v*.sql")]
29
+ return 1 if files.empty?
30
+
31
+ files.map { |f| f.match(/_v(\d+)\.sql$/)[1].to_i }.max
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ class FileVersion
5
+ attr_reader :path, :name, :version
6
+
7
+ def initialize(path)
8
+ @path = Pathname.new(path)
9
+ @name = @path.basename.to_s.sub(/_v\d+\.sql$/, "")
10
+ @version = extract_version
11
+ end
12
+
13
+ def sql_definition
14
+ File.read(path).strip
15
+ end
16
+
17
+ private
18
+
19
+ def extract_version
20
+ if (match = @path.basename.to_s.match(/_v(\d+)\.sql$/))
21
+ match[1].to_i
22
+ else
23
+ 0
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ class Railtie < Rails::Railtie
5
+ initializer "postgres_aggregates.load" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.include PgTypes::SchemaStatements
8
+ ActiveRecord::Migration::CommandRecorder.include PgTypes::CommandRecorder
9
+ ActiveRecord::SchemaDumper.prepend PgTypes::SchemaDumper
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ module SchemaDumper
5
+ def tables(stream)
6
+ # First dump types
7
+ dump_custom_types(stream)
8
+ stream.puts
9
+
10
+ super
11
+ end
12
+
13
+ private
14
+
15
+ def dump_custom_types(stream)
16
+ type_versions = {}
17
+ Dir.glob(File.join(Dir.pwd, "db/types/*_v*.sql")).each do |file|
18
+ file_version = FileVersion.new(file)
19
+ type_versions[file_version.name] ||= []
20
+ type_versions[file_version.name] << file_version
21
+ end
22
+
23
+ return if type_versions.empty?
24
+
25
+ stream.puts " # These are custom PostgreSQL types that were defined"
26
+
27
+ latest_versions = type_versions.transform_values do |versions|
28
+ versions.max_by(&:version)
29
+ end
30
+
31
+ latest_versions.keys.sort.each do |type_name|
32
+ file_version = latest_versions[type_name]
33
+ all_versions = type_versions[type_name].map(&:version).sort
34
+ version_comment = all_versions.size > 1 ? " -- versions: #{all_versions.join(", ")}" : ""
35
+
36
+ # Remove any leading/trailing whitespace from SQL definition
37
+ sql_def = file_version.sql_definition.strip
38
+
39
+ stream.puts <<-TYPE
40
+ create_type "#{type_name}", sql_definition: <<-SQL#{version_comment}
41
+ #{sql_def}
42
+ SQL
43
+
44
+ TYPE
45
+ end
46
+
47
+ stream.puts
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ module SchemaStatements
5
+ def create_type(name, version: nil, sql_definition: nil)
6
+ raise ArgumentError, "Must provide either sql_definition or version" if sql_definition.nil? && version.nil?
7
+
8
+ if sql_definition
9
+ execute sql_definition
10
+ else
11
+ # Try both Rails.root and current directory for type definition
12
+ type_definition = PgTypes::TypeDefinition.new(name, version: version)
13
+ paths = [
14
+ type_definition.path,
15
+ File.join(Dir.pwd, "db", "types", "#{name}_v#{version}.sql")
16
+ ]
17
+
18
+ sql_file = paths.find { |path| File.exist?(path) }
19
+
20
+ raise ArgumentError, "Could not find type definition file in paths: #{paths.join(", ")}" unless sql_file
21
+
22
+ execute File.read(sql_file)
23
+ end
24
+ end
25
+
26
+ def drop_type(name, force: false)
27
+ force_clause = force ? " CASCADE" : ""
28
+ # Drop the type and any dependent objects when force: true
29
+ execute "DROP TYPE IF EXISTS #{name}#{force_clause}"
30
+
31
+ # Ensure any dependent objects are really gone when using CASCADE
32
+ return unless force
33
+
34
+ execute <<-SQL
35
+ DO $$
36
+ BEGIN
37
+ EXECUTE format('DROP TABLE IF EXISTS %I CASCADE', 'test_contacts');
38
+ END;
39
+ $$;
40
+ SQL
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ class TypeDefinition
5
+ attr_reader :name, :version
6
+
7
+ def initialize(name, version:)
8
+ @name = name
9
+ @version = version
10
+ end
11
+
12
+ def to_sql
13
+ File.read(path)
14
+ end
15
+
16
+ def path
17
+ Rails.root.join("db", "types", "#{name}_v#{version}.sql").to_s
18
+ end
19
+
20
+ def full_name
21
+ name.to_s.include?(".") ? name.to_s : "public.#{name}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgTypes
4
+ VERSION = "0.2.1"
5
+ end
data/lib/pg_types.rb ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/railtie"
4
+
5
+ require_relative "pg_types/file_version"
6
+ require_relative "pg_types/type_definition"
7
+ require_relative "pg_types/schema_statements"
8
+ require_relative "pg_types/command_recorder"
9
+ require_relative "pg_types/schema_dumper"
10
+ require_relative "pg_types/railtie"
11
+
12
+ module PgTypes
13
+ class Error < StandardError; end
14
+
15
+ class << self
16
+ def database
17
+ ActiveRecord::Base.connection
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module PgAggregates
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pg_types
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - mhenrixon
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: railties
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '6.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '6.1'
55
+ description: |
56
+ Manage PostgreSQL custom types (composite types, enums, domains) in your Rails application with
57
+ versioned migrations and schema handling. This cuts the need for keeping a structure.sql
58
+ while still maintaining proper type definitions in your Rails application.
59
+ email:
60
+ - mikael@mhenrixon.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - Appraisals
66
+ - CHANGELOG.md
67
+ - LICENSE.txt
68
+ - README.md
69
+ - gemfiles/rails_6.1.gemfile
70
+ - gemfiles/rails_6.1.gemfile.lock
71
+ - gemfiles/rails_7.0.gemfile
72
+ - gemfiles/rails_7.0.gemfile.lock
73
+ - gemfiles/rails_7.1.gemfile
74
+ - gemfiles/rails_7.1.gemfile.lock
75
+ - lib/generators/pg/type/aggregate_generator.rb
76
+ - lib/generators/pg/type/templates/migration.rb.erb
77
+ - lib/generators/pg/type/templates/type.sql.erb
78
+ - lib/generators/pg/type/type_generator.rb
79
+ - lib/pg_types.rb
80
+ - lib/pg_types/command_recorder.rb
81
+ - lib/pg_types/file_version.rb
82
+ - lib/pg_types/railtie.rb
83
+ - lib/pg_types/schema_dumper.rb
84
+ - lib/pg_types/schema_statements.rb
85
+ - lib/pg_types/type_definition.rb
86
+ - lib/pg_types/version.rb
87
+ - sig/pg_aggregates.rbs
88
+ homepage: https://github.com/mhenrixon/pg_types
89
+ licenses:
90
+ - MIT
91
+ metadata:
92
+ homepage_uri: https://github.com/mhenrixon/pg_types
93
+ source_code_uri: https://github.com/mhenrixon/pg_types
94
+ changelog_uri: https://github.com/mhenrixon/pg_types/blob/main/CHANGELOG.md
95
+ documentation_uri: https://github.com/mhenrixon/pg_types#readme
96
+ bug_tracker_uri: https://github.com/mhenrixon/pg_types/issues
97
+ rubygems_mfa_required: 'true'
98
+ github_repo: ssh://github.com/mhenrixon/pg_types
99
+ funding_uri: https://github.com/sponsors/mhenrixon
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 3.0.0
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 3.5.22
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Rails integration for PostgreSQL custom types
119
+ test_files: []