sql_enum 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd16ecd7dbef436bf1613fa7b841e3575db7528778cee563fcb7128ae48ed24b
4
- data.tar.gz: 474745a0a9090a1e9203493c6f4864a69fb07f622ece22e3db432142ef2de953
3
+ metadata.gz: 7ba5a5a0695bc9c11496ca90509646d98e2e005e7c89664aba78acb1de45d270
4
+ data.tar.gz: 1cb90fe77fcc9b7e2d84c0fe9b9b41ddee264de6e488d5de8dbc9462371a8ecd
5
5
  SHA512:
6
- metadata.gz: 62b096819785f82af237b66cfe9cab150037e229796dda1e760f52e91140a8bcae092126e5bac5b0f51ea72cd25abad51ee9ad8f68b5ceb70b39682e18e367ce
7
- data.tar.gz: 2c702f4de99f2c50513ae2b1cbcf17a349601d63b7e59a09750488358bca93632219924f444270a33befee9a28153970e0d129e1d20f62d30dc94ac028359d46
6
+ metadata.gz: 795a28c30fc3fddb87865fc82325243c67a009694c409ffe880dace43c0d601cdcc32b4d9806a9d9c3220616dcc82be9b0e57ca8ccb3bb14c2d6562457c588a5
7
+ data.tar.gz: 67835417b809b63b7d97deb3531d059f3df63d1450406b0216cb81540a7276c691635126da7afdbf1dcf87fb128f7fe63cc8e196073fac55254e321ca1b66b58
data/.env ADDED
@@ -0,0 +1,3 @@
1
+ MYSQL_DATABASE=sql_enum_test
2
+ MYSQL_USER=sql_enum
3
+ MYSQL_PASSWORD=sql_enum
@@ -0,0 +1,16 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+
8
+ jobs:
9
+ rspec:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+
15
+ - name: Test
16
+ run: docker-compose run --rm rspec
data/Dockerfile ADDED
@@ -0,0 +1,12 @@
1
+ FROM ruby:3.0
2
+
3
+ # throw errors if Gemfile has been modified since Gemfile.lock
4
+ RUN bundle config --global frozen 1
5
+
6
+ WORKDIR /usr/src/app
7
+
8
+ # Bundler caching
9
+ RUN mkdir -p lib/sql_enum
10
+ COPY lib/sql_enum/version.rb ./lib/sql_enum/
11
+ COPY sql_enum.gemspec Gemfile Gemfile.lock ./
12
+ RUN bundle install
data/Gemfile.lock CHANGED
@@ -1,28 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sql_enum (0.2.2)
4
+ sql_enum (0.3.0)
5
5
  activerecord (>= 5.0)
6
+ activesupport (>= 5.0)
7
+ mysql2
6
8
 
7
9
  GEM
8
10
  remote: https://gem-proxy.chime.com/
9
11
  specs:
10
- activemodel (6.1.3.2)
11
- activesupport (= 6.1.3.2)
12
- activerecord (6.1.3.2)
13
- activemodel (= 6.1.3.2)
14
- activesupport (= 6.1.3.2)
15
- activesupport (6.1.3.2)
12
+ activemodel (6.1.4.1)
13
+ activesupport (= 6.1.4.1)
14
+ activerecord (6.1.4.1)
15
+ activemodel (= 6.1.4.1)
16
+ activesupport (= 6.1.4.1)
17
+ activesupport (6.1.4.1)
16
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
19
  i18n (>= 1.6, < 2)
18
20
  minitest (>= 5.1)
19
21
  tzinfo (~> 2.0)
20
22
  zeitwerk (~> 2.3)
21
- concurrent-ruby (1.1.8)
23
+ concurrent-ruby (1.1.9)
22
24
  diff-lcs (1.3)
23
25
  i18n (1.8.10)
24
26
  concurrent-ruby (~> 1.0)
25
27
  minitest (5.14.4)
28
+ mysql2 (0.5.3)
26
29
  rake (13.0.3)
27
30
  rspec (3.7.0)
28
31
  rspec-core (~> 3.7.0)
@@ -39,16 +42,16 @@ GEM
39
42
  rspec-support (3.7.1)
40
43
  tzinfo (2.0.4)
41
44
  concurrent-ruby (~> 1.0)
42
- zeitwerk (2.4.2)
45
+ zeitwerk (2.5.1)
43
46
 
44
47
  PLATFORMS
45
48
  ruby
46
49
 
47
50
  DEPENDENCIES
48
- bundler (~> 1.16)
51
+ bundler
49
52
  rake (~> 13.0)
50
53
  rspec (~> 3.0)
51
54
  sql_enum!
52
55
 
53
56
  BUNDLED WITH
54
- 1.17.3
57
+ 2.2.30
data/README.md CHANGED
@@ -48,9 +48,11 @@ class User < ActiveRecord::Base
48
48
  end
49
49
  ```
50
50
 
51
- ## TODO
51
+ ## Development
52
52
 
53
- * Enable passing `null` argument
53
+ ### Testing
54
+
55
+ Run `docker-compose run --rm rspec` to run the specs in a docker container alongside Mysql.
54
56
 
55
57
  ## Contributing
56
58
 
@@ -0,0 +1,23 @@
1
+ services:
2
+ rspec:
3
+ build: .
4
+ environment:
5
+ DATABASE_URL: "mysql2://${MYSQL_USER}:${MYSQL_PASSWORD}@mysql/${MYSQL_DATABASE}"
6
+ volumes:
7
+ - ./:/usr/src/app/
8
+ depends_on:
9
+ mysql:
10
+ condition: service_healthy
11
+ command: bundle exec rspec
12
+
13
+ mysql:
14
+ image: mysql:5.7
15
+ environment:
16
+ - MYSQL_ALLOW_EMPTY_PASSWORD=yes
17
+ - MYSQL_DATABASE
18
+ - MYSQL_USER
19
+ - MYSQL_PASSWORD
20
+ healthcheck:
21
+ test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
22
+ timeout: 20s
23
+ retries: 10
@@ -0,0 +1,3 @@
1
+ ActiveSupport.on_load(:active_record) do
2
+ extend SqlEnum::ClassMethods
3
+ end
@@ -0,0 +1,21 @@
1
+ module SqlEnum
2
+ module ClassMethods
3
+ def sql_enum(column_name, options = {})
4
+ # Query values
5
+ enum_column = EnumColumn.new(table_name, column_name)
6
+ values = enum_column.values.to_h { |value| [value.to_sym, value.to_s] }
7
+
8
+ # Check option defaults
9
+ prefix = options.fetch(:_prefix, !!SqlEnum.configuration&.default_prefix)
10
+ suffix = options.fetch(:_suffix, !!SqlEnum.configuration&.default_suffix)
11
+
12
+ # Define enum using Rails enum
13
+ enum(column_name => values, _prefix: prefix, _suffix: suffix)
14
+
15
+ # Override reader to return symbols
16
+ concerning "SqlEnum#{column_name.to_s.camelize}" do
17
+ define_method(column_name) { super()&.to_sym }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ module SqlEnum
2
+ class Configuration
3
+ attr_accessor :default_prefix, :default_suffix
4
+
5
+ def initialize
6
+ @default_prefix = false
7
+ @default_suffix = false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqlEnum
4
+ EnumColumn = Struct.new(:table_name, :column_name) do
5
+ def values
6
+ schema_values.to_s.scan(/\w+/).reject { |v| v == 'enum' }
7
+ end
8
+
9
+ private
10
+
11
+ def schema_values
12
+ ActiveRecord::Base.connection.exec_query(schema_values_query).rows.dig(0, 0)
13
+ end
14
+
15
+ def database_name
16
+ if ActiveRecord::Base.respond_to?(:connection_db_config)
17
+ ActiveRecord::Base.connection_db_config.configuration_hash[:database]
18
+ else
19
+ ActiveRecord::Base.connection_config.values_at(:database, :database_name).find(&:present?)
20
+ end
21
+ end
22
+
23
+ def schema_values_query
24
+ <<~EOSQL
25
+ SELECT column_type
26
+ FROM information_schema.COLUMNS
27
+ WHERE TABLE_SCHEMA = '#{database_name}'
28
+ AND TABLE_NAME = '#{table_name}'
29
+ AND COLUMN_NAME = '#{column_name}'
30
+ EOSQL
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module SqlEnum
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/sql_enum.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'active_record'
2
-
3
1
  module SqlEnum
4
2
  class << self
5
3
  attr_accessor :configuration
@@ -9,22 +7,18 @@ module SqlEnum
9
7
  self.configuration ||= Configuration.new
10
8
  yield(configuration)
11
9
  end
12
-
13
- class Configuration
14
- attr_accessor :default_prefix, :default_suffix
15
-
16
- def initialize
17
- @default_prefix = false
18
- @default_suffix = false
19
- end
20
- end
21
10
  end
22
11
 
23
- require_relative 'active_record/enum/enum_type'
12
+ require 'active_record'
13
+ require 'active_support/core_ext/module/concerning'
14
+
24
15
  require_relative 'active_record/type/enum'
25
- require_relative 'active_record/enum_override'
26
- require_relative 'active_record/fixtures_override'
27
16
  require_relative 'active_record/connection_adapters/mysql2'
28
17
  require_relative 'active_record/connection_adapters/abstract_mysql'
29
18
  require_relative 'active_record/connection_adapters/mysql/column_methods'
30
- require_relative "sql_enum/version"
19
+
20
+ require_relative 'sql_enum/version'
21
+ require_relative 'sql_enum/configuration'
22
+ require_relative 'sql_enum/enum_column'
23
+ require_relative 'sql_enum/class_methods'
24
+ require_relative 'sql_enum/active_record'
data/sql_enum.gemspec CHANGED
@@ -1,6 +1,6 @@
1
-
2
1
  lib = File.expand_path("../lib", __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
4
  require "sql_enum/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
@@ -20,8 +20,11 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
+ spec.add_dependency "activesupport", ">= 5.0"
23
24
  spec.add_dependency "activerecord", ">= 5.0"
24
- spec.add_development_dependency "bundler", "~> 1.16"
25
+ spec.add_dependency "mysql2"
26
+
27
+ spec.add_development_dependency "bundler"
25
28
  spec.add_development_dependency "rake", "~> 13.0"
26
29
  spec.add_development_dependency "rspec", "~> 3.0"
27
30
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sql_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fletcher Fowler
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-13 00:00:00.000000000 Z
11
+ date: 2021-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: activerecord
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,20 +38,34 @@ dependencies:
24
38
  - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mysql2
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
- - - "~>"
59
+ - - ">="
32
60
  - !ruby/object:Gem::Version
33
- version: '1.16'
61
+ version: '0'
34
62
  type: :development
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
- - - "~>"
66
+ - - ">="
39
67
  - !ruby/object:Gem::Version
40
- version: '1.16'
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -73,10 +101,13 @@ executables: []
73
101
  extensions: []
74
102
  extra_rdoc_files: []
75
103
  files:
104
+ - ".env"
105
+ - ".github/workflows/tests.yml"
76
106
  - ".gitignore"
77
107
  - ".rspec"
78
108
  - ".travis.yml"
79
109
  - CODE_OF_CONDUCT.md
110
+ - Dockerfile
80
111
  - Gemfile
81
112
  - Gemfile.lock
82
113
  - LICENSE.txt
@@ -84,14 +115,16 @@ files:
84
115
  - Rakefile
85
116
  - bin/console
86
117
  - bin/setup
118
+ - docker-compose.yml
87
119
  - lib/active_record/connection_adapters/abstract_mysql.rb
88
120
  - lib/active_record/connection_adapters/mysql/column_methods.rb
89
121
  - lib/active_record/connection_adapters/mysql2.rb
90
- - lib/active_record/enum/enum_type.rb
91
- - lib/active_record/enum_override.rb
92
- - lib/active_record/fixtures_override.rb
93
122
  - lib/active_record/type/enum.rb
94
123
  - lib/sql_enum.rb
124
+ - lib/sql_enum/active_record.rb
125
+ - lib/sql_enum/class_methods.rb
126
+ - lib/sql_enum/configuration.rb
127
+ - lib/sql_enum/enum_column.rb
95
128
  - lib/sql_enum/version.rb
96
129
  - sql_enum.gemspec
97
130
  homepage: https://github.com/1debit/sql_enum
@@ -113,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
146
  - !ruby/object:Gem::Version
114
147
  version: '0'
115
148
  requirements: []
116
- rubygems_version: 3.1.6
149
+ rubygems_version: 3.2.22
117
150
  signing_key:
118
151
  specification_version: 4
119
152
  summary: Enable using native sql enums
@@ -1,41 +0,0 @@
1
- module ActiveRecord
2
- module Enum
3
- class EnumType < Type::Value # :nodoc:
4
- delegate :type, to: :subtype
5
-
6
- def initialize(name, mapping, subtype)
7
- @name = name
8
- @mapping = mapping
9
- @subtype = subtype
10
- end
11
-
12
- def cast(value)
13
- return if value.blank?
14
-
15
- if valid?(value)
16
- value.to_sym
17
- else
18
- assert_valid_value(value)
19
- end
20
- end
21
-
22
- def deserialize(value)
23
- value&.to_sym
24
- end
25
-
26
- def serialize(value)
27
- value ? value.to_s : nil
28
- end
29
-
30
- def valid?(value)
31
- mapping.include?(value.to_s)
32
- end
33
-
34
- def assert_valid_value(value)
35
- unless value.blank? || valid?(value)
36
- raise ArgumentError, "'#{value}' is not a valid #{name}"
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,86 +0,0 @@
1
- require 'active_record/enum'
2
-
3
- module ActiveRecord
4
- module Enum
5
- def sql_enum(name, options={})
6
- enum_prefix = options.delete(:_prefix)
7
- enum_suffix = options.delete(:_suffix)
8
-
9
- enum_prefix ||= name if SqlEnum.configuration&.default_prefix
10
- enum_suffix ||= name if SqlEnum.configuration&.default_suffix
11
-
12
- klass = self
13
- enum_values = Array.new
14
- name = name.to_sym
15
-
16
- detect_enum_conflict!(name, name.to_s.pluralize, true)
17
- klass.singleton_class.send(:define_method, name.to_s.pluralize) { enum_values.map(&:to_sym) }
18
-
19
- detect_enum_conflict!(name, name)
20
- detect_enum_conflict!(name, "#{name}=")
21
-
22
- attr = attribute_alias?(name) ? attribute_alias(name) : name
23
-
24
- if Rails.version >= '6.1'
25
- decorate_attribute_type(name) do |subtype|
26
- EnumType.new(attr, enum_values, subtype)
27
- end
28
- else
29
- decorate_attribute_type(attr, :enum) do |subtype|
30
- EnumType.new(attr, enum_values, subtype)
31
- end
32
- end
33
-
34
- enum_values = values(name)
35
- enum_values.each do |value|
36
- if enum_prefix == true
37
- prefix = "#{name}_"
38
- elsif enum_prefix
39
- prefix = "#{enum_prefix}_"
40
- end
41
- if enum_suffix == true
42
- suffix = "_#{name}"
43
- elsif enum_suffix
44
- suffix = "_#{enum_suffix}"
45
- end
46
-
47
- value_method_name = "#{prefix}#{value}#{suffix}"
48
-
49
- # def active?() status == 0 end
50
- klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
51
- define_method("#{value_method_name}?") { self[attr] == value.to_sym }
52
-
53
- # def active!() update! status: :active end
54
- klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
55
- define_method("#{value_method_name}!") { update!(attr => value) }
56
-
57
- # scope :active, -> { where status: 0 }
58
- klass.send(:detect_enum_conflict!, name, value_method_name, true)
59
- klass.scope value_method_name, -> { where(attr => value) }
60
- end
61
- defined_enums[name.to_s] = enum_values
62
- end
63
-
64
- def values(name)
65
- schema_values(name).to_s.scan(/\w+/).reject{|v| v == 'enum'}
66
- end
67
-
68
- def schema_values(name)
69
- ActiveRecord::Base.connection.exec_query(schema_values_query(name)).rows.dig(0,0)
70
- end
71
-
72
- def database_name
73
- ActiveRecord::Base.connection_config[:database]
74
- end
75
-
76
- def schema_values_query(name)
77
- %{
78
- SELECT column_type
79
- FROM information_schema.COLUMNS
80
- WHERE TABLE_SCHEMA = '#{database_name}'
81
- AND TABLE_NAME = '#{table_name}'
82
- AND COLUMN_NAME = '#{name}'
83
- }
84
- end
85
- end
86
- end
@@ -1,79 +0,0 @@
1
- require 'active_record/fixtures'
2
-
3
- module ActiveRecord
4
- class FixtureSet
5
- def table_rows
6
- now = config.default_timezone == :utc ? Time.now.utc : Time.now
7
-
8
- # allow a standard key to be used for doing defaults in YAML
9
- fixtures.delete('DEFAULTS')
10
-
11
- # track any join tables we need to insert later
12
- rows = Hash.new { |h,table| h[table] = [] }
13
-
14
- rows[table_name] = fixtures.map do |label, fixture|
15
- row = fixture.to_hash
16
-
17
- if model_class
18
- # fill in timestamp columns if they aren't specified and the model is set to record_timestamps
19
- if model_class.record_timestamps
20
- timestamp_column_names.each do |c_name|
21
- row[c_name] = now unless row.key?(c_name)
22
- end
23
- end
24
-
25
- # interpolate the fixture label
26
- row.each do |key, value|
27
- row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
28
- end
29
-
30
- # generate a primary key if necessary
31
- if has_primary_key_column? && !row.include?(primary_key_name)
32
- row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
33
- end
34
-
35
- # Resolve enums
36
- # model_class.defined_enums.each do |name, values|
37
- # if row.include?(name)
38
- # row[name] = values.fetch(row[name], row[name])
39
- # end
40
- # end
41
-
42
- # If STI is used, find the correct subclass for association reflection
43
- reflection_class =
44
- if row.include?(inheritance_column_name)
45
- row[inheritance_column_name].constantize rescue model_class
46
- else
47
- model_class
48
- end
49
-
50
- reflection_class._reflections.each_value do |association|
51
- case association.macro
52
- when :belongs_to
53
- # Do not replace association name with association foreign key if they are named the same
54
- fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
55
-
56
- if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
57
- if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
58
- # support polymorphic belongs_to as "label (Type)"
59
- row[association.foreign_type] = $1
60
- end
61
-
62
- fk_type = reflection_class.type_for_attribute(fk_name).type
63
- row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
64
- end
65
- when :has_many
66
- if association.options[:through]
67
- add_join_records(rows, row, HasManyThroughProxy.new(association))
68
- end
69
- end
70
- end
71
- end
72
-
73
- row
74
- end
75
- rows
76
- end
77
- end
78
- end
79
-