enum_kit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.rspec +2 -0
- data/.rubocop.yml +21 -0
- data/.travis.yml +13 -0
- data/Gemfile +5 -0
- data/Guardfile +17 -0
- data/LICENSE +21 -0
- data/README.md +82 -0
- data/Rakefile +8 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/config.ru +9 -0
- data/enum_kit.gemspec +35 -0
- data/lib/enum_kit/active_record_extensions/connection_adapters/postgresql/column_dumper.rb +29 -0
- data/lib/enum_kit/active_record_extensions/connection_adapters/postgresql/schema_dumper.rb +29 -0
- data/lib/enum_kit/active_record_extensions/connection_adapters/postgresql_adapter.rb +74 -0
- data/lib/enum_kit/active_record_extensions/migration/command_recorder.rb +45 -0
- data/lib/enum_kit/active_record_extensions/schema_dumper.rb +31 -0
- data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/column_methods.rb +32 -0
- data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/oid/enum.rb +32 -0
- data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/oid/type_map_initializer.rb +27 -0
- data/lib/enum_kit/active_record_patches/enum/enum_type.rb +25 -0
- data/lib/enum_kit/active_record_patches/enum.rb +39 -0
- data/lib/enum_kit/active_record_patches/validations/pg_enum_validator.rb +31 -0
- data/lib/enum_kit/constants.rb +7 -0
- data/lib/enum_kit/helpers.rb +84 -0
- data/lib/enum_kit.rb +62 -0
- data/spec/active_record/base_spec.rb +15 -0
- data/spec/active_record/connection_adapters/postgresql_adapter_spec.rb +62 -0
- data/spec/active_record/validations/pg_enum_validator_spec.rb +19 -0
- data/spec/enum_kit/constants_spec.rb +11 -0
- data/spec/enum_kit/helpers_spec.rb +106 -0
- data/spec/internal/app/models/shirt.rb +7 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/db/schema.rb +10 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/spec_helper.rb +96 -0
- metadata +231 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0edccc6b488902ea7344f63e24014979d60f2a315c79335fc959c7cfeafb1473
|
4
|
+
data.tar.gz: 2776e409ad4108dfaf9b504d6cdb3d43cafe3368e9889d05f27635f8240c33d6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7f41dc0fd5399088b5d5cdc02fb2bd48fd0a1c3ff3b4fdb44d53920d9c6d4b12ece952c2d6ee9c3174423bd79d3f96b7babd1e7a107315acb35ea58a6aa8cda5
|
7
|
+
data.tar.gz: c43cd3f3a197c828d958de2f5374d6a8d98d1ff1d6f381ec8d1265753d081682cca917af8cd220317ca0014313812102bfe6cde7e999913ab161fac480002395
|
data/.gitignore
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Packages #
|
2
|
+
############
|
3
|
+
*.7z
|
4
|
+
*.dmg
|
5
|
+
*.gz
|
6
|
+
*.iso
|
7
|
+
*.jar
|
8
|
+
*.rar
|
9
|
+
*.tar
|
10
|
+
*.zip
|
11
|
+
|
12
|
+
# Logs #
|
13
|
+
########
|
14
|
+
*.log
|
15
|
+
|
16
|
+
# Databases #
|
17
|
+
#############
|
18
|
+
*.sql
|
19
|
+
*.sqlite
|
20
|
+
|
21
|
+
# OS Files #
|
22
|
+
############
|
23
|
+
.DS_Store
|
24
|
+
.Trashes
|
25
|
+
ehthumbs.db
|
26
|
+
Icon?
|
27
|
+
Thumbs.db
|
28
|
+
|
29
|
+
# Vagrant #
|
30
|
+
###########
|
31
|
+
.vagrant
|
32
|
+
|
33
|
+
# Ruby Files #
|
34
|
+
##############
|
35
|
+
/.bundle/
|
36
|
+
/.yardoc
|
37
|
+
/Gemfile.lock
|
38
|
+
/_yardoc/
|
39
|
+
/coverage/
|
40
|
+
/doc/
|
41
|
+
/pkg/
|
42
|
+
/spec/reports/
|
43
|
+
/spec/examples.txt
|
44
|
+
/tmp/
|
45
|
+
/vendor/bundle/
|
46
|
+
*.gem
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- 'bin/**/*'
|
4
|
+
|
5
|
+
Metrics/AbcSize:
|
6
|
+
Max: 30
|
7
|
+
|
8
|
+
Metrics/LineLength:
|
9
|
+
Max: 120
|
10
|
+
|
11
|
+
Metrics/BlockLength:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Metrics/ClassLength:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Metrics/MethodLength:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Style/Documentation:
|
21
|
+
Enabled: false
|
data/.travis.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.6.5
|
4
|
+
services:
|
5
|
+
- postgresql
|
6
|
+
before_install:
|
7
|
+
- gem update --system
|
8
|
+
- gem install bundler
|
9
|
+
before_script:
|
10
|
+
- psql -c 'CREATE DATABASE enum_kit_test;' -U postgres
|
11
|
+
env:
|
12
|
+
global:
|
13
|
+
- DATABASE_URL="postgresql://127.0.0.1:5432/enum_kit_test"
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
4
|
+
require 'guard/rspec/dsl'
|
5
|
+
|
6
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
7
|
+
|
8
|
+
# RSpec files
|
9
|
+
rspec = dsl.rspec
|
10
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
11
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
12
|
+
watch(rspec.spec_files)
|
13
|
+
|
14
|
+
# Ruby files
|
15
|
+
ruby = dsl.ruby
|
16
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
17
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Nialto Services
|
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,82 @@
|
|
1
|
+
# EnumKit
|
2
|
+
|
3
|
+
EnumKit provides native support for PostgreSQL enums in Ruby on Rails projects.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
You can install **EnumKit** using the following command:
|
8
|
+
|
9
|
+
$ gem install enum_kit
|
10
|
+
|
11
|
+
Or, by adding the following to your `Gemfile`:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'enum_kit', '~> 0.1'
|
15
|
+
```
|
16
|
+
|
17
|
+
### Usage
|
18
|
+
|
19
|
+
Here's a sample migration file which creates the enum `:shirt_size`, then adds the column `:size` to the `:shirts`
|
20
|
+
table using the `:shirt_size` enum as the underlying type:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
class CreateShirts < ActiveRecord::Migration[6.0]
|
24
|
+
def change
|
25
|
+
create_enum :shirt_size, %i[small medium large]
|
26
|
+
|
27
|
+
create_table :shirts do |t|
|
28
|
+
t.string :name
|
29
|
+
t.enum :size, name: :shirt_size
|
30
|
+
|
31
|
+
t.timestamps
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
You can remove the enum later using something similar to this:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
class DropShirts < ActiveRecord::Migration[6.0]
|
41
|
+
def change
|
42
|
+
drop_table :shirts
|
43
|
+
drop_enum :shirt_size
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
Once you've defined an enum in a migration file, you can use it in the associated model:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
class Shirt < ActiveRecord::Base
|
52
|
+
pg_enum :size
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
Note that you don't need to define the enum's cases again.
|
57
|
+
The `pg_enum` method automatically queries the database when Rails boots for the acceptable values!
|
58
|
+
|
59
|
+
---
|
60
|
+
|
61
|
+
When setting the enum to an unsupported value, an exception is raised. This can be problematic in cases where you don't
|
62
|
+
have control over the input (such as when using APIs).
|
63
|
+
|
64
|
+
To improve this, you can optionally specify that exceptions should not be raised on a per enum basis. Note that when
|
65
|
+
opting for this feature, you'd ideally specify a validation to capture any unsupported values:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class Shirt < ActiveRecord::Base
|
69
|
+
pg_enum :size, exceptions: false
|
70
|
+
|
71
|
+
validates :size, pg_enum: true
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
The above prevents exceptions from being raised and checks that the assigned value is one of the cases supported by the
|
76
|
+
enum.
|
77
|
+
|
78
|
+
## Development
|
79
|
+
|
80
|
+
After checking out the repo, run `bundle exec rake spec` to run the tests.
|
81
|
+
|
82
|
+
To install this gem onto your machine, run `bundle exec rake install`.
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
data/config.ru
ADDED
data/enum_kit.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'enum_kit/constants'
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = 'enum_kit'
|
10
|
+
spec.version = EnumKit::VERSION
|
11
|
+
spec.authors = ['Nialto Services']
|
12
|
+
spec.email = ['support@nialtoservices.co.uk']
|
13
|
+
|
14
|
+
spec.summary = 'Native PostgreSQL enum support for Ruby on Rails.'
|
15
|
+
spec.homepage = 'https://github.com/nialtoservices/enum_kit'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.metadata['yard.run'] = 'yri'
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'activerecord', '>= 4.0.0'
|
25
|
+
spec.add_runtime_dependency 'activesupport', '>= 4.0.0'
|
26
|
+
spec.add_runtime_dependency 'pg'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
29
|
+
spec.add_development_dependency 'combustion', '~> 1.1'
|
30
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7'
|
31
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
33
|
+
spec.add_development_dependency 'rspec-rails', '~> 3.8'
|
34
|
+
spec.add_development_dependency 'yard', '~> 0.9.20'
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module EnumKit
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ActiveRecordExtensions
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module ConnectionAdapters
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module PostgreSQL
|
15
|
+
# :nodoc:
|
16
|
+
#
|
17
|
+
module ColumnDumper
|
18
|
+
# :nodoc:
|
19
|
+
#
|
20
|
+
def prepare_column_options(column)
|
21
|
+
spec = super
|
22
|
+
spec[:name] = column.sql_type.inspect if column.type == :enum
|
23
|
+
spec
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module EnumKit
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ActiveRecordExtensions
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module ConnectionAdapters
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module PostgreSQL
|
15
|
+
# :nodoc:
|
16
|
+
#
|
17
|
+
module SchemaDumper
|
18
|
+
# :nodoc:
|
19
|
+
#
|
20
|
+
def prepare_column_options(column)
|
21
|
+
spec = super
|
22
|
+
spec[:name] = column.sql_type.inspect if column.type == :enum
|
23
|
+
spec
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module EnumKit
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ActiveRecordExtensions
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module ConnectionAdapters
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module PostgreSQLAdapter
|
15
|
+
# @return [String] An SQL query that returns all available enum types in the database.
|
16
|
+
#
|
17
|
+
ENUM_QUERY = <<~SQL
|
18
|
+
SELECT
|
19
|
+
pg_type.OID,
|
20
|
+
pg_type.typname,
|
21
|
+
pg_type.typtype,
|
22
|
+
array_to_string(array_agg(pg_enum.enumlabel ORDER BY pg_enum.enumsortorder), '\t\t', '') as values
|
23
|
+
FROM pg_type
|
24
|
+
LEFT JOIN pg_enum ON pg_enum.enumtypid = pg_type.oid
|
25
|
+
WHERE pg_type.typtype = 'e'
|
26
|
+
GROUP BY pg_type.OID, pg_type.typname, pg_type.typtype
|
27
|
+
ORDER BY pg_type.typname
|
28
|
+
SQL
|
29
|
+
|
30
|
+
# @return [Hash] The enum types available in the database.
|
31
|
+
#
|
32
|
+
def enums
|
33
|
+
@enums ||= select_all(ENUM_QUERY.tr("\n", ' ').strip).each_with_object({}) do |row, enums|
|
34
|
+
enums[row['typname'].to_sym] = row['values'].split("\t\t")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Create a new enum type in the database.
|
39
|
+
#
|
40
|
+
# @param name [Symbol] The name of the new enum type.
|
41
|
+
# @param values [Array] The enum's acceptable values.
|
42
|
+
#
|
43
|
+
def create_enum(name, values)
|
44
|
+
name = EnumKit.sanitize_name!(name)
|
45
|
+
values = EnumKit.sanitize_values!(values)
|
46
|
+
|
47
|
+
execute "CREATE TYPE #{name} AS ENUM #{EnumKit.sqlize(values)}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Drop an existing enum type from the database.
|
51
|
+
#
|
52
|
+
# @param name [Symbol] The name of the existing enum type.
|
53
|
+
#
|
54
|
+
def drop_enum(name)
|
55
|
+
execute "DROP TYPE #{name}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# :nodoc:
|
59
|
+
#
|
60
|
+
def migration_keys
|
61
|
+
super + [:name]
|
62
|
+
end
|
63
|
+
|
64
|
+
# :nodoc:
|
65
|
+
#
|
66
|
+
def prepare_column_options(column, types)
|
67
|
+
spec = super(column, types)
|
68
|
+
spec[:name] = column.cast_type.type.inspect if column.type == :enum
|
69
|
+
spec
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module EnumKit
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ActiveRecordExtensions
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module Migration
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module CommandRecorder
|
15
|
+
# :nodoc:
|
16
|
+
#
|
17
|
+
def create_enum(*args)
|
18
|
+
record(:create_enum, args)
|
19
|
+
end
|
20
|
+
|
21
|
+
# :nodoc:
|
22
|
+
#
|
23
|
+
def drop_enum(*args)
|
24
|
+
record(:drop_enum, args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# :nodoc:
|
28
|
+
#
|
29
|
+
def invert_create_enum(args)
|
30
|
+
record(:drop_enum, args.first)
|
31
|
+
end
|
32
|
+
|
33
|
+
# :nodoc:
|
34
|
+
#
|
35
|
+
def invert_drop_enum(args)
|
36
|
+
unless args.length > 1
|
37
|
+
raise ::ActiveRecord::IrreversibleMigration, 'drop_enum is only reversible if given an Array of values.'
|
38
|
+
end
|
39
|
+
|
40
|
+
record(:create_enum, args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module EnumKit
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ActiveRecordExtensions
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module SchemaDumper
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
def tables(stream)
|
15
|
+
export_enums(stream)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
# :nodoc:
|
20
|
+
#
|
21
|
+
def export_enums(stream)
|
22
|
+
@connection.enums.each do |name, values|
|
23
|
+
values = values.map(&:inspect).join(', ')
|
24
|
+
stream.puts " create_enum #{name.inspect}, [#{values}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
stream.puts if @connection.enums.any?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module ActiveRecord
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ConnectionAdapters
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module PostgreSQL
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module ColumnMethods
|
15
|
+
# Create an enum column with the provided name.
|
16
|
+
#
|
17
|
+
# By default, the enum type will match the name of the column.
|
18
|
+
# You can change this behaviour by providing the enum type as an option under the `:name` key.
|
19
|
+
#
|
20
|
+
# @example Creating a user role.
|
21
|
+
# t.enum :role, name: :user_role
|
22
|
+
#
|
23
|
+
# @param name [String] The name of the enum column.
|
24
|
+
# @param options [Hash] The options (including the name of the enum type).
|
25
|
+
#
|
26
|
+
def enum(name, options = {})
|
27
|
+
column(name, options[:name] || name, options.except(:name))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module ActiveRecord
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ConnectionAdapters
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module PostgreSQL
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module OID
|
15
|
+
# :nodoc:
|
16
|
+
#
|
17
|
+
class Enum < Type::Value
|
18
|
+
# @return [String] The PostgreSQL type for the enum.
|
19
|
+
#
|
20
|
+
attr_reader :name
|
21
|
+
|
22
|
+
# :nodoc:
|
23
|
+
#
|
24
|
+
def initialize(options = {})
|
25
|
+
@name = options.delete(:name).to_sym
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/oid/type_map_initializer.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module ActiveRecord
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module ConnectionAdapters
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
module PostgreSQL
|
12
|
+
# :nodoc:
|
13
|
+
#
|
14
|
+
module OID
|
15
|
+
# :nodoc:
|
16
|
+
#
|
17
|
+
class TypeMapInitializer
|
18
|
+
# :nodoc:
|
19
|
+
#
|
20
|
+
def register_enum_type(row)
|
21
|
+
register row['oid'], ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Enum.new(name: row['typname'])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module ActiveRecord
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module Enum
|
9
|
+
# :nodoc:
|
10
|
+
#
|
11
|
+
class EnumType < Type::Value
|
12
|
+
# @return [Boolean] Whether to prevent an exception from being raised when the enum is set to an invalid value.
|
13
|
+
#
|
14
|
+
attr_accessor :disable_exceptions
|
15
|
+
|
16
|
+
# :nodoc:
|
17
|
+
#
|
18
|
+
def assert_valid_value(value)
|
19
|
+
return value if value.blank? || mapping.key?(value) || mapping.value?(value) || disable_exceptions
|
20
|
+
|
21
|
+
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module ActiveRecord
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module Enum
|
9
|
+
# Retrieve the acceptable values for the enum type associated with the given column.
|
10
|
+
#
|
11
|
+
# @param [String, Symbol] The name of an enum column.
|
12
|
+
# @return [Array] The acceptable values for the enum type associated with the column.
|
13
|
+
#
|
14
|
+
def pg_enum_values(name)
|
15
|
+
# Determine the PostgreSQL type name for the enum.
|
16
|
+
type = type_for_attribute(name)
|
17
|
+
type = type.instance_eval { subtype } if type.is_a?(ActiveRecord::Enum::EnumType)
|
18
|
+
|
19
|
+
# Query the PostgreSQL database for the enum's acceptable values.
|
20
|
+
connection.enums[type.name]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Define a PostgreSQL enum type.
|
24
|
+
#
|
25
|
+
# @param name [String] The name of an enum column.
|
26
|
+
# @param options [Hash] The options.
|
27
|
+
#
|
28
|
+
def pg_enum(name, options = {})
|
29
|
+
values = pg_enum_values(name).map { |value| [value.to_sym, value.to_s] }
|
30
|
+
|
31
|
+
enum(name => Hash[values])
|
32
|
+
|
33
|
+
enum = type_for_attribute(name)
|
34
|
+
enum.disable_exceptions = options.key?(:exceptions) && !options[:exceptions]
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|