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 +7 -0
- data/Appraisals +16 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +169 -0
- data/gemfiles/rails_6.1.gemfile +24 -0
- data/gemfiles/rails_6.1.gemfile.lock +176 -0
- data/gemfiles/rails_7.0.gemfile +24 -0
- data/gemfiles/rails_7.0.gemfile.lock +176 -0
- data/gemfiles/rails_7.1.gemfile +24 -0
- data/gemfiles/rails_7.1.gemfile.lock +207 -0
- data/lib/generators/pg/type/aggregate_generator.rb +50 -0
- data/lib/generators/pg/type/templates/migration.rb.erb +5 -0
- data/lib/generators/pg/type/templates/type.sql.erb +9 -0
- data/lib/generators/pg/type/type_generator.rb +63 -0
- data/lib/pg_types/command_recorder.rb +34 -0
- data/lib/pg_types/file_version.rb +27 -0
- data/lib/pg_types/railtie.rb +13 -0
- data/lib/pg_types/schema_dumper.rb +50 -0
- data/lib/pg_types/schema_statements.rb +43 -0
- data/lib/pg_types/type_definition.rb +24 -0
- data/lib/pg_types/version.rb +5 -0
- data/lib/pg_types.rb +20 -0
- data/sig/pg_aggregates.rbs +4 -0
- metadata +119 -0
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
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,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
|
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
|
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: []
|