literal_enums-rails 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +102 -0
- data/Rakefile +3 -0
- data/lib/literal_enums/enum.rb +7 -0
- data/lib/literal_enums/rails/associations.rb +32 -0
- data/lib/literal_enums/rails/enum_serializer.rb +22 -0
- data/lib/literal_enums/rails/enum_type.rb +22 -0
- data/lib/literal_enums/rails/railtie.rb +9 -0
- data/lib/literal_enums/rails/version.rb +5 -0
- data/lib/literal_enums/rails.rb +12 -0
- data/lib/tasks/literal_enums/rails_tasks.rake +4 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 01da8c12a247c4aea59cfc6595f4f5f9b5c8dd69ebdab550ba86ac7f0c5508c7
|
4
|
+
data.tar.gz: 4d813f97175ce52f2fe87b2accaa6e0897fc7c78c4d1e9e0b8e8e4c774e9a6ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 15677e95690ef2605599bb96102a0223e0b2db9c9a78b93f4b627221ff359b15decdcbd5e4360ec0d2d21b9ad3d8179613c3a33b7aeb014f64ef64331d1f10f8
|
7
|
+
data.tar.gz: 1ee2822126919e1c1b02205378bb860116d92613eeaac2d6528aca97e0ee30ce8b98ea018b034c3f44bed8989a3fc51fb83cf5938e1dd7f4ceedc9d0d6f224fe
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Joel Drapper
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# literal_enums-rails
|
2
|
+
|
3
|
+
Provides additional support for Rails with LiteralEnums.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
Please see `literal_enums` for further documentaiton.
|
7
|
+
|
8
|
+
### ActiveJob
|
9
|
+
|
10
|
+
Literal Enums are automatically serialised and deserialised for ActiveJob. You don't need to do anythign special to enable this. Just treat enums are normal arguments.
|
11
|
+
|
12
|
+
### ActiveModel
|
13
|
+
|
14
|
+
You can add Enum attributes to any `ActiveModel` class as an `attribute`.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
class Article < ApplicationRecord
|
18
|
+
class State < Enum
|
19
|
+
Published()
|
20
|
+
Unpublished()
|
21
|
+
end
|
22
|
+
|
23
|
+
attribute :state, Enum[State]
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Note: you need to specify exactly which Enum class the attribute is expected to be. This is so it can deserialise and cast a value to the correct member.
|
28
|
+
|
29
|
+
If you're storing the values in a database, make sure the tyep of the value matches the type of the database field. If the members don't specify values, their names will be used instead.
|
30
|
+
|
31
|
+
These are not the same as Rails enums as they don't add mysterious scopes and predicates to the model itself.
|
32
|
+
|
33
|
+
Instead of asking the Article if it is published, you'd need to inspect the Article's state attribute directly.
|
34
|
+
|
35
|
+
You can do this with a comparator e.g. `==` or with a polymorphic predicate.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# The Rails way
|
39
|
+
Article.published?
|
40
|
+
|
41
|
+
# The Literal Enums way
|
42
|
+
Article.state.published?
|
43
|
+
```
|
44
|
+
|
45
|
+
Scoping the predicate to the state attribute itself reduces the risk of collision. It also means the enum makes no assumptions about the business logic of your model. It may not be the case that whole article is published because the state is published.
|
46
|
+
|
47
|
+
You can use Enums like any other value when writing database queries in ActiveRecord. For example, you might define a scope like this:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
scope :published -> { where(state: State::Published, publish_at: ..Time.current) }
|
51
|
+
```
|
52
|
+
|
53
|
+
You can also define associations from an enum to relevant records.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
class Article < ApplicationRecord
|
57
|
+
class State < Enum
|
58
|
+
Published()
|
59
|
+
Unpublished()
|
60
|
+
|
61
|
+
has_many :articles
|
62
|
+
end
|
63
|
+
|
64
|
+
attribute :state, Enum[State]
|
65
|
+
end
|
66
|
+
|
67
|
+
Article::State::Published.articles # returns a relation to articles with the Published state.
|
68
|
+
```
|
69
|
+
|
70
|
+
`has_many` optionally accepts a `class_name` for the model to query, as well as the name of the enum attribute.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
has_many :publication_events, class_name: "ArticlePublicationEvent", as: :publication_status
|
74
|
+
|
75
|
+
# Translates to this
|
76
|
+
def self.publication_events
|
77
|
+
ArticlePublicationEvent.where(publication_status: self)
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
## Installation
|
82
|
+
Add this line to your application's Gemfile:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
gem "literal_enums-rails"
|
86
|
+
```
|
87
|
+
|
88
|
+
And then execute:
|
89
|
+
```bash
|
90
|
+
$ bundle
|
91
|
+
```
|
92
|
+
|
93
|
+
Or install it yourself as:
|
94
|
+
```bash
|
95
|
+
$ gem install literal_enums-rails
|
96
|
+
```
|
97
|
+
|
98
|
+
## Contributing
|
99
|
+
Contribution directions go here.
|
100
|
+
|
101
|
+
## License
|
102
|
+
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,32 @@
|
|
1
|
+
module LiteralEnums
|
2
|
+
module Rails
|
3
|
+
module Associations
|
4
|
+
private
|
5
|
+
|
6
|
+
def has_many(name, class_name: nil, as: nil)
|
7
|
+
class_name ||= name.to_s.classify
|
8
|
+
full_class_name = class_name.constantize.name
|
9
|
+
foreign_key = as || relative_foreign_key(self.name, relative_to: full_class_name)
|
10
|
+
|
11
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
12
|
+
def #{name}
|
13
|
+
#{class_name}.where(#{foreign_key}: self)
|
14
|
+
end
|
15
|
+
RUBY
|
16
|
+
end
|
17
|
+
|
18
|
+
def relative_foreign_key(name, relative_to:)
|
19
|
+
path = name.split("::")
|
20
|
+
other_path = relative_to.split("::")
|
21
|
+
|
22
|
+
path
|
23
|
+
.zip(other_path)
|
24
|
+
.drop_while { |a, b| a == b }
|
25
|
+
.transpose
|
26
|
+
.first
|
27
|
+
&.join("_")
|
28
|
+
&.underscore()
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LiteralEnums
|
2
|
+
module Rails
|
3
|
+
class EnumSerializer < ::ActiveJob::Serializers::ObjectSerializer
|
4
|
+
def serialize?(object)
|
5
|
+
object.is_a? Enum
|
6
|
+
end
|
7
|
+
|
8
|
+
def serialize(enum)
|
9
|
+
super(
|
10
|
+
{
|
11
|
+
"class" => enum.class.name,
|
12
|
+
"value" => enum.value
|
13
|
+
}
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def deserialize(hash)
|
18
|
+
hash["class"].constantize.cast(hash["value"])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LiteralEnums
|
2
|
+
module Rails
|
3
|
+
class EnumType < ActiveModel::Type::String
|
4
|
+
def initialize(enum)
|
5
|
+
@enum = enum
|
6
|
+
end
|
7
|
+
|
8
|
+
def type
|
9
|
+
:enum
|
10
|
+
end
|
11
|
+
|
12
|
+
def cast_value(value)
|
13
|
+
return value if value.is_a?(@enum)
|
14
|
+
@enum.cast(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def serialize(value)
|
18
|
+
value.value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "literal_enums/rails/version"
|
2
|
+
require "literal_enums/rails/enum_type"
|
3
|
+
require "literal_enums/rails/enum_serializer"
|
4
|
+
require "literal_enums/rails/associations"
|
5
|
+
require "literal_enums/rails/railtie"
|
6
|
+
require "literal_enums/enum"
|
7
|
+
|
8
|
+
module LiteralEnums
|
9
|
+
module Rails
|
10
|
+
# Your code goes here...
|
11
|
+
end
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: literal_enums-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joel Drapper
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-03-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: literal_enums
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mocha
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.13.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.13.0
|
55
|
+
description: Rails support for Literal Enums.
|
56
|
+
email:
|
57
|
+
- joel@drapper.me
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- lib/literal_enums/enum.rb
|
66
|
+
- lib/literal_enums/rails.rb
|
67
|
+
- lib/literal_enums/rails/associations.rb
|
68
|
+
- lib/literal_enums/rails/enum_serializer.rb
|
69
|
+
- lib/literal_enums/rails/enum_type.rb
|
70
|
+
- lib/literal_enums/rails/railtie.rb
|
71
|
+
- lib/literal_enums/rails/version.rb
|
72
|
+
- lib/tasks/literal_enums/rails_tasks.rake
|
73
|
+
homepage: https://github.com/joeldrapper/literal_enums-rails
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata:
|
77
|
+
homepage_uri: https://github.com/joeldrapper/literal_enums-rails
|
78
|
+
source_code_uri: https://github.com/joeldrapper/literal_enums-rails
|
79
|
+
changelog_uri: https://github.com/joeldrapper/literal_enums-rails
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubygems_version: 3.3.7
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Literal Enums in Rails.
|
99
|
+
test_files: []
|