taylors_enum 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 22eddc0a8e5096da1be305ffcaf244c99e9cd53f502acf7d5d3827d64ceb5781
4
+ data.tar.gz: 9dcbda215ceb54dc6aef75950ad45dfa8da07e20c88ac456f1aac22804f0c5e6
5
+ SHA512:
6
+ metadata.gz: 7c8cd3171a1e074a18550b8055ba93cb008f636ac9d350dddbe7387a9e4d5848fc00565aeff7fb6a9382fffa3afa555e7f1e27033de0ebc53cbb525677390a7f
7
+ data.tar.gz: d672df8ce78450646179c625f27e596a74e9118f64140db5addf70b6c1d933049a3d368a143742222c9f5b15e8b7a5d076582b09a8c64de286e06de35701f4c5
data/.rubocop.yml ADDED
@@ -0,0 +1,58 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: single_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: single_quotes
11
+
12
+ Style/TrailingCommaInHashLiteral:
13
+ Enabled: true
14
+ EnforcedStyle: comma
15
+
16
+ Style/TrailingCommaInArguments:
17
+ Enabled: true
18
+ EnforcedStyleForMultiline: comma
19
+
20
+ Style/StderrPuts:
21
+ Enabled: false
22
+
23
+ Style/Documentation:
24
+ Enabled: false
25
+
26
+ Style/FrozenStringLiteralComment:
27
+ Enabled: false
28
+
29
+ Style/FormatStringToken:
30
+ Enabled: false
31
+
32
+ Layout/MultilineMethodCallIndentation:
33
+ Enabled: true
34
+ EnforcedStyle: indented
35
+
36
+ Layout/LineLength:
37
+ Enabled: false
38
+
39
+ Metrics/BlockLength:
40
+ Enabled: false
41
+
42
+ Metrics/ModuleLength:
43
+ Enabled: false
44
+
45
+ Metrics/AbcSize:
46
+ Enabled: false
47
+
48
+ Metrics/CyclomaticComplexity:
49
+ Enabled: false
50
+
51
+ Metrics/MethodLength:
52
+ Enabled: false
53
+
54
+ Metrics/PerceivedComplexity:
55
+ Enabled: false
56
+
57
+ Metrics/ClassLength:
58
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-06-03
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in taylors_enum.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+
10
+ gem 'minitest', '~> 5.0'
11
+
12
+ gem 'rubocop', '~> 1.21'
data/Gemfile.lock ADDED
@@ -0,0 +1,72 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ taylors_enum (0.1.0)
5
+ activesupport (>= 4.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (7.0.3)
11
+ activesupport (= 7.0.3)
12
+ activerecord (7.0.3)
13
+ activemodel (= 7.0.3)
14
+ activesupport (= 7.0.3)
15
+ activesupport (7.0.3)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ ast (2.4.2)
21
+ byebug (11.1.3)
22
+ coderay (1.1.3)
23
+ concurrent-ruby (1.1.10)
24
+ i18n (1.10.0)
25
+ concurrent-ruby (~> 1.0)
26
+ method_source (1.0.0)
27
+ minitest (5.15.0)
28
+ parallel (1.22.1)
29
+ parser (3.1.2.0)
30
+ ast (~> 2.4.1)
31
+ pg (1.2.3)
32
+ pry (0.13.1)
33
+ coderay (~> 1.1)
34
+ method_source (~> 1.0)
35
+ pry-byebug (3.9.0)
36
+ byebug (~> 11.0)
37
+ pry (~> 0.13.0)
38
+ rainbow (3.1.1)
39
+ rake (13.0.6)
40
+ regexp_parser (2.5.0)
41
+ rexml (3.2.5)
42
+ rubocop (1.30.0)
43
+ parallel (~> 1.10)
44
+ parser (>= 3.1.0.0)
45
+ rainbow (>= 2.2.2, < 4.0)
46
+ regexp_parser (>= 1.8, < 3.0)
47
+ rexml (>= 3.2.5, < 4.0)
48
+ rubocop-ast (>= 1.18.0, < 2.0)
49
+ ruby-progressbar (~> 1.7)
50
+ unicode-display_width (>= 1.4.0, < 3.0)
51
+ rubocop-ast (1.18.0)
52
+ parser (>= 3.1.1.0)
53
+ ruby-progressbar (1.11.0)
54
+ tzinfo (2.0.4)
55
+ concurrent-ruby (~> 1.0)
56
+ unicode-display_width (2.1.0)
57
+
58
+ PLATFORMS
59
+ arm64-darwin-21
60
+
61
+ DEPENDENCIES
62
+ activerecord (>= 4.2)
63
+ minitest (~> 5.0)
64
+ pg (~> 1.2.0)
65
+ pry
66
+ pry-byebug (~> 3.9.0)
67
+ rake (~> 13.0)
68
+ rubocop (~> 1.21)
69
+ taylors_enum!
70
+
71
+ BUNDLED WITH
72
+ 2.3.11
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 PJ
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,176 @@
1
+ # TaylorsEnum
2
+
3
+ TaylorsEnum is a gem that builds on top of ActiveRecord's built in [enums](https://api.rubyonrails.org/v5.2.4.4/classes/ActiveRecord/Enum.html#method-i-enum). Specifically, it will:
4
+
5
+ ###### - Define additional methods to make it clearer which values exist in Rails-land, and which in the database
6
+ In Rails:
7
+ ```
8
+ class Album < ActiveRecord::Base
9
+ self.table_name = 'albums'
10
+ enum name: %w[debut fearless speak_now red nineteen_eighty_nine reputation lover folklore evermore]
11
+ end
12
+
13
+ [1] pry(#<TestDefault>)> Album.names
14
+ => {"debut"=>0, "fearless"=>1, "speak_now"=>2, "red"=>3, "nineteen_eighty_nine"=>4, "reputation"=>5, "lover"=>6, "folklore"=>7, "evermore"=>8}
15
+ ```
16
+
17
+ With TaylorsEnum:
18
+ ```
19
+ class AlbumBase < Album
20
+ taylors_enum name: %w[debut fearless speak_now red nineteen_eighty_nine reputation lover folklore evermore]
21
+ end
22
+
23
+ [2] pry(#<TestDefault>)> AlbumBase.name_rails_values
24
+ => ["debut", "fearless", "speak_now", "red", "nineteen_eighty_nine", "reputation", "lover", "folklore", "evermore"]
25
+ [3] pry(#<TestDefault>)> AlbumBase.name_database_values
26
+ => ["debut", "fearless", "speak_now", "red", "nineteen_eighty_nine", "reputation", "lover", "folklore", "evermore"]
27
+
28
+ ```
29
+
30
+
31
+ ###### - Define constants for each value provided
32
+ ```
33
+ class AlbumBase < Album
34
+ taylors_enum name: %w[debut fearless speak_now red nineteen_eighty_nine reputation lover folklore evermore]
35
+ end
36
+
37
+ [5] pry(#<TestDefault>)> AlbumBase::FOLKLORE
38
+ => "folklore"
39
+ [6] pry(#<TestDefault>)> AlbumBase::EVERMORE
40
+ => "evermore"
41
+ # etc.
42
+
43
+ ```
44
+
45
+ ###### - Enables support for all the enum goodness when enumerating classes for Single Table Inheritance
46
+ ```
47
+ module SingleTableInheritanceAlbums
48
+ class SingleTableInheritanceAlbum < ActiveRecord::Base
49
+ self.table_name = 'single_table_inheritance_albums'
50
+
51
+ taylors_enum type: %w[
52
+ SingleTableInheritanceAlbums::Debut
53
+ SingleTableInheritanceAlbums::Fearless
54
+ SingleTableInheritanceAlbums::SpeakNow
55
+ SingleTableInheritanceAlbums::Red
56
+ SingleTableInheritanceAlbums::NineteenEightyNine
57
+ SingleTableInheritanceAlbums::Reputation
58
+ SingleTableInheritanceAlbums::Lover
59
+ SingleTableInheritanceAlbums::Folklore
60
+ SingleTableInheritanceAlbums::Evermore
61
+ ], single_table_inheritance: true
62
+ end
63
+
64
+ class Debut < SingleTableInheritanceAlbum; end
65
+ class Fearless < SingleTableInheritanceAlbum; end
66
+ class SpeakNow < SingleTableInheritanceAlbum; end
67
+ class Red < SingleTableInheritanceAlbum; end
68
+ class NineteenEightyNine < SingleTableInheritanceAlbum; end
69
+ class Reputation < SingleTableInheritanceAlbum; end
70
+ class Lover < SingleTableInheritanceAlbum; end
71
+ class Folklore < SingleTableInheritanceAlbum; end
72
+ class Evermore < SingleTableInheritanceAlbum; end
73
+ end
74
+
75
+ [5] pry(#<TestSingleTableInheritance>)> album = ::SingleTableInheritanceAlbums::Debut.create
76
+ => #<SingleTableInheritanceAlbums::Debut:0x000000010581a708 id: 2, type: "SingleTableInheritanceAlbums::Debut", created_at: 2022-06-04 14:34:24.951932 UTC, updated_at: 2022-06-04 14:34:24.951932 UTC>
77
+ [6] pry(#<TestSingleTableInheritance>)> album.type
78
+ => "SingleTableInheritanceAlbums::Debut"
79
+ [7] pry(#<TestSingleTableInheritance>)> album.debut?
80
+ => true
81
+ [8] pry(#<TestSingleTableInheritance>)> album.fearless!
82
+ => true
83
+ [9] pry(#<TestSingleTableInheritance>)> album.debut?
84
+ => false
85
+ [10] pry(#<TestSingleTableInheritance>)> album.fearless?
86
+ => true
87
+ [11] pry(#<TestSingleTableInheritance>)> album.type
88
+ => "SingleTableInheritanceAlbums::Fearless"
89
+ [12] pry(#<TestSingleTableInheritance>)> ::SingleTableInheritanceAlbums::SingleTableInheritanceAlbum.fearless
90
+ => [#<SingleTableInheritanceAlbums::Fearless:0x00000001059821e0 id: 1, type: "SingleTableInheritanceAlbums::Fearless", created_at: 2022-06-04 14:33:55.178418 UTC, updated_at: 2022-06-04 14:33:55.178418 UTC>,
91
+ #<SingleTableInheritanceAlbums::Fearless:0x0000000105981a10 id: 2, type: "SingleTableInheritanceAlbums::Fearless", created_at: 2022-06-04 14:34:24.951932 UTC, updated_at: 2022-06-04 14:34:50.616316 UTC>]
92
+ [13] pry(#<TestSingleTableInheritance>)> ::SingleTableInheritanceAlbums::SingleTableInheritanceAlbum.fearless.to_sql
93
+ => "SELECT \"single_table_inheritance_albums\".* FROM \"single_table_inheritance_albums\" WHERE \"single_table_inheritance_albums\".\"type\" = 'SingleTableInheritanceAlbums::Fearless'"
94
+ ```
95
+
96
+ ###### - Enables support for all the enum goodness when enumerating classes for Polymorphic Associations
97
+ Note: this excludes the `<attribute>!` method to update a value, as, as I write this, I can't conceive of a scenario in which you'd want to update just the type, and not also the ID, of an associated object. If you want to do this, you can still do this manually via the `ActiveRecord#update` method.
98
+
99
+ ```
100
+ class Award < ActiveRecord::Base
101
+ self.table_name = 'awards'
102
+ belongs_to :awardable, polymorphic: true
103
+ taylors_enum awardable_type: %w[Album Song], polymorphic: true
104
+ end
105
+
106
+ [1] pry(#<TestPolymorphic>)> song = Song.create!
107
+ => #<Song:0x0000000105beddd0 id: 1, name: nil, created_at: 2022-06-04 14:39:38.837973 UTC, updated_at: 2022-06-04 14:39:38.837973 UTC>
108
+ [2] pry(#<TestPolymorphic>)> album = AlbumBase.create!(name: :folklore)
109
+ => #<AlbumBase:0x0000000105c36c10 id: 1, name: "folklore", created_at: 2022-06-04 14:39:43.001592 UTC, updated_at: 2022-06-04 14:39:43.001592 UTC>
110
+ [3] pry(#<TestPolymorphic>)> song_award = Award.create!(awardable: song)
111
+ => #<Award:0x0000000105c77030 id: 1, awardable_type: "Song", awardable_id: "1", created_at: 2022-06-04 14:39:46.714235 UTC, updated_at: 2022-06-04 14:39:46.714235 UTC>
112
+ [4] pry(#<TestPolymorphic>)> album_award = Award.create!(awardable: album)
113
+ => #<Award:0x0000000105cb4ac0 id: 2, awardable_type: "Album", awardable_id: "1", created_at: 2022-06-04 14:39:49.444071 UTC, updated_at: 2022-06-04 14:39:49.444071 UTC>
114
+ [5] pry(#<TestPolymorphic>)> song_award.song?
115
+ => true
116
+ [6] pry(#<TestPolymorphic>)> song_award.album?
117
+ => false
118
+ [7] pry(#<TestPolymorphic>)> album_award.song?
119
+ => false
120
+ [8] pry(#<TestPolymorphic>)> album_award.album?
121
+ => true
122
+ [9] pry(#<TestPolymorphic>)> Award.song
123
+ => [#<Award:0x0000000105dbfca8 id: 1, awardable_type: "Song", awardable_id: "1", created_at: 2022-06-04 14:39:46.714235 UTC, updated_at: 2022-06-04 14:39:46.714235 UTC>]
124
+ [10] pry(#<TestPolymorphic>)> Award.song.to_sql
125
+ => "SELECT \"awards\".* FROM \"awards\" WHERE \"awards\".\"awardable_type\" = 'Song'"
126
+ ```
127
+
128
+
129
+ ## Installation
130
+
131
+ Install the gem and add to the application's Gemfile by executing:
132
+
133
+ $ bundle add taylors_enum
134
+
135
+ If bundler is not being used to manage dependencies, install the gem by executing:
136
+
137
+ $ gem install taylors_enum
138
+
139
+ ## Usage
140
+
141
+ Using taylors_enum is simple! Once the gem is installed, just add `taylors_enum <my_column>: ['array', 'of', 'values']` to any model that ultimately inherits from `ActiveRecord::Base`.
142
+
143
+ The values that you pass will be the values that are stored in the database. taylors_enum will then generate a companion for each value that will be used to define constants, `?` methods to check if an object has the given value in the specified column, `!` methods to update the column to that value, and scopes to query for records with that value. See the top of this README for what this looks like in practice.
144
+
145
+ taylors_enum also takes a series of options, provided as a hash:
146
+ - `prefix`: defaults to `nil`. If `true` is passed, the name of the column will be prepended to the start of the helper methods, scopes, and constants. If a string is passed, the given string will be prepended to the start of the helper methods, scopes, and constants.
147
+
148
+ - `suffix`: defaults to `nil`. If `true` is passed, the name of the column will be appended to the end of the helper methods, scopes, and constants. If a string is passed, the given string will be appended to the end of the helper methods, scopes, and constants.
149
+
150
+ - `constants`: defaults to `true`. If `false` is passed, constants will not be defined. This can be helpful for migrating onto taylors_enum, if you already have constants defined for certain enum values.
151
+
152
+ - `validations`: defaults to `true`. If `false` is passed, validations, `nil` will be allowed as a value in the specified column.
153
+
154
+ - `single_table_inheritance`: defaults to `false`. When using taylors_enum to help with columns on [Single Table Inheritance](https://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html) models, pass this value as `true`, otherwise things won't work, and then you'll be sad.
155
+
156
+ - `polymorphic`: defaults to `false`. When using taylors_enum to help with type columns for [polymorphic associations](https://guides.rubyonrails.org/association_basics.html#polymorphic-associations), pass this value as `true`; this will ensure validations are run correctly, against database values rather than Rails values, and will also not create a `!` method to update the value of the column.
157
+
158
+ If you want to see the base Rails value that will be used to generate the `value?` and `value!` methods, that `VALUE` constants, and the `value` scopes, you can load
159
+
160
+ ## Development
161
+
162
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
163
+
164
+ You'll also need to have a working database in order to run the tests. First, make sure you have [Postgres](https://www.postgresql.org/) installed. You can easily do this on a Mac with [Homebrew](https://wiki.postgresql.org/wiki/Homebrew).
165
+
166
+ From there, run `createdb taylors_enum` in the terminal to create a database with the required name. Then, run `psql taylors_enum` to open a terminal to that database, and run `create user postgres;` to create a user with the correct username for the test suite to connect to it. The database connection config is specified in `test/database.yml`
167
+
168
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
169
+
170
+ ## Contributing
171
+
172
+ Bug reports and pull requests are welcome on GitHub at https://github.com/isitpj/taylors_enum.
173
+
174
+ ## License
175
+
176
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/test_*.rb']
10
+ end
11
+
12
+ require 'rubocop/rake_task'
13
+
14
+ RuboCop::RakeTask.new
15
+
16
+ task default: %i[test rubocop]
@@ -0,0 +1,7 @@
1
+ module TaylorsEnum
2
+ module ActiveRecord
3
+ ActiveSupport.on_load :active_record do
4
+ extend ::TaylorsEnum::ActiveRecord::TaylorsEnum::ClassMethods
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,157 @@
1
+ module TaylorsEnum
2
+ module ActiveRecord
3
+ module TaylorsEnum
4
+ module ClassMethods
5
+ DEFAULT_OPTIONS = {
6
+ prefix: nil, # can be true, false, or a string; if true, will use the column_name as the default value
7
+ suffix: nil, # can be true, false, or a string; if true, will use the column_name as the default value
8
+ constants: true, # can be true or false
9
+ validations: true, # can be true or false; TODO: allow a hash of validations args to be passed
10
+ single_table_inheritance: false,
11
+ polymorphic: false,
12
+ column: nil # this is set by the first argument passed to taylors_enum
13
+ }.with_indifferent_access.freeze
14
+
15
+ def taylors_enum(**enum_args)
16
+ enum_args, *options = *enum_args
17
+ enum_column, raw_values = *enum_args
18
+
19
+ options = DEFAULT_OPTIONS
20
+ .merge(**options.to_h)
21
+ .merge(column: enum_column)
22
+ .with_indifferent_access
23
+
24
+ values = format_values(raw_values, options: options)
25
+
26
+ define_list_methods!(values, column: enum_column)
27
+
28
+ define_constants!(values) if options[:constants].present?
29
+
30
+ # NOTE: when relying on the default rails enum, we validate against the rails-side values, as enum does its own custom validation; however, taylors_enum validates against the database-side values, as it relies on active_record validations
31
+ values_to_validate = options[:single_table_inheritance] || options[:polymorphic] ? values.values : values.keys
32
+ enforce_validations!(values: values_to_validate, column: enum_column) if options[:validations].present?
33
+
34
+ if options[:single_table_inheritance]
35
+ manually_define_single_table_inheritance_enum_methods(values, column: enum_column)
36
+ elsif options[:polymorphic]
37
+ manually_define_polymorphic_enum_methods(values, column: enum_column)
38
+ else
39
+ enum(enum_column => values) unless options[:single_table_inheritance]
40
+ end
41
+ end
42
+
43
+ def check_rails_value_for(database_value, column: nil, prefix: nil, suffix: nil)
44
+ format_values(
45
+ [database_value],
46
+ options: {
47
+ column: column,
48
+ prefix: prefix,
49
+ suffix: suffix
50
+ },
51
+ ).keys.first
52
+ end
53
+
54
+ private
55
+
56
+ def manually_define_single_table_inheritance_enum_methods(values, column:)
57
+ values.each do |rails_value, database_value|
58
+ define_boolean_method(rails_value, database_value, column)
59
+ define_update_method(rails_value, database_value, column)
60
+ define_scope(rails_value, database_value, column)
61
+ end
62
+ end
63
+
64
+ # NOTE: skip defining the update method for polymorphic, as it makes little sense to update the associated type without also updating the corresponding id
65
+ def manually_define_polymorphic_enum_methods(values, column:)
66
+ values.each do |rails_value, database_value|
67
+ define_boolean_method(rails_value, database_value, column)
68
+ define_scope(rails_value, database_value, column)
69
+ end
70
+ end
71
+
72
+ # def active?() status == "active" end
73
+ def define_boolean_method(rails_value, database_value, column)
74
+ method_name = "#{rails_value}?"
75
+ detect_method_conflict(column, method_name, class_method: false)
76
+ define_method(method_name) { self[column] == database_value }
77
+ end
78
+
79
+ # def active!() update!(status: :active) end
80
+ def define_update_method(rails_value, database_value, column)
81
+ method_name = "#{rails_value}!"
82
+ detect_method_conflict(column, method_name, class_method: false)
83
+ define_method(method_name) { update!(column => database_value) }
84
+ end
85
+
86
+ # scope :active, -> { where(status: :active) }
87
+ def define_scope(rails_value, database_value, column)
88
+ method_name = rails_value
89
+ detect_method_conflict(column, method_name, class_method: true)
90
+ scope method_name, -> { where(column => database_value) }
91
+ end
92
+
93
+ def detect_method_conflict(column, method_name, class_method:)
94
+ send(
95
+ :detect_enum_conflict!,
96
+ column,
97
+ method_name,
98
+ class_method,
99
+ )
100
+ end
101
+
102
+ def define_list_methods!(values, column:)
103
+ define_singleton_method("#{column}_rails_values") do
104
+ values.keys
105
+ end
106
+
107
+ define_singleton_method("#{column}_database_values") do
108
+ values.values
109
+ end
110
+ end
111
+
112
+ def define_constants!(values)
113
+ values.each do |rails_value, database_value|
114
+ const_set(rails_value.upcase, database_value)
115
+ end
116
+ end
117
+
118
+ def enforce_validations!(values:, column:)
119
+ validates column, presence: true, inclusion: { in: values, message: "%{value} is not a valid #{column}" }
120
+ end
121
+
122
+ def format_values(values, options:)
123
+ prefix = generate_prefix_name(options[:prefix], column: options[:column])
124
+ suffix = generate_suffix_name(options[:suffix], column: options[:column])
125
+
126
+ values.map do |value|
127
+ formatted_value = value.to_s.demodulize.underscore
128
+ [
129
+ "#{prefix}#{formatted_value}#{suffix}",
130
+ value
131
+ ]
132
+ end.to_h
133
+ end
134
+
135
+ def generate_prefix_name(prefix, column:)
136
+ enum_prefix = generate_nfix_name(prefix, column: column)
137
+ enum_prefix.present? ? "#{enum_prefix}_" : ''
138
+ end
139
+
140
+ def generate_suffix_name(suffix, column:)
141
+ enum_suffix = generate_nfix_name(suffix, column: column)
142
+ enum_suffix.present? ? "_#{enum_suffix}" : ''
143
+ end
144
+
145
+ def generate_nfix_name(nfix, column:)
146
+ if nfix == true
147
+ column
148
+ elsif nfix
149
+ nfix
150
+ else
151
+ ''
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TaylorsEnum
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'taylors_enum/version'
4
+
5
+ module TaylorsEnum
6
+ class Error < StandardError; end
7
+ require 'active_support'
8
+ require 'active_support/core_ext/hash'
9
+ require 'taylors_enum/active_record/active_record'
10
+ require 'taylors_enum/active_record/taylors_enum'
11
+ end
@@ -0,0 +1,4 @@
1
+ module TaylorsEnum
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/taylors_enum/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'taylors_enum'
7
+ spec.version = TaylorsEnum::VERSION
8
+ spec.authors = ['Cassie Johnstone']
9
+ spec.email = ['peter.wdj@gmail.com']
10
+
11
+ spec.summary = 'Better enums in Rails.'
12
+ spec.description = 'Helper methods around enumerable values in Rails, including enums, polymorphic associations, and single-table inheritance.'
13
+ spec.homepage = 'https://github.com/isitpj/taylors_enum'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 2.6.0'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = spec.homepage
19
+ spec.metadata['changelog_uri'] = 'https://github.com/isitpj/taylors_enum/blob/main/CHANGELOG.md'
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
+ end
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.add_dependency 'activesupport', '>= 4.2'
33
+ spec.add_development_dependency 'activerecord', '>= 4.2'
34
+ spec.add_development_dependency 'pg', '~> 1.2.0'
35
+ spec.add_development_dependency 'pry'
36
+ spec.add_development_dependency 'pry-byebug', '~> 3.9.0'
37
+
38
+ # For more information and examples about making a new gem, check out our
39
+ # guide at: https://bundler.io/guides/creating_gem.html
40
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: taylors_enum
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cassie Johnstone
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-06-04 00:00:00.000000000 Z
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: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pg
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.2.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.9.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.9.0
83
+ description: Helper methods around enumerable values in Rails, including enums, polymorphic
84
+ associations, and single-table inheritance.
85
+ email:
86
+ - peter.wdj@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".rubocop.yml"
92
+ - CHANGELOG.md
93
+ - Gemfile
94
+ - Gemfile.lock
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - lib/taylors_enum.rb
99
+ - lib/taylors_enum/active_record/active_record.rb
100
+ - lib/taylors_enum/active_record/taylors_enum.rb
101
+ - lib/taylors_enum/version.rb
102
+ - sig/taylors_enum.rbs
103
+ - taylors_enum.gemspec
104
+ homepage: https://github.com/isitpj/taylors_enum
105
+ licenses:
106
+ - MIT
107
+ metadata:
108
+ homepage_uri: https://github.com/isitpj/taylors_enum
109
+ source_code_uri: https://github.com/isitpj/taylors_enum
110
+ changelog_uri: https://github.com/isitpj/taylors_enum/blob/main/CHANGELOG.md
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: 2.6.0
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubygems_version: 3.3.3
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Better enums in Rails.
130
+ test_files: []