enumy 0.1.5 → 0.2.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: 5eb558fc84613c310a1f660e944233954a74d9c613dc777ac68d67305d55b168
4
- data.tar.gz: 057cf069fe5810e2ef4af942c1b52f7ab253e6bcef4726bf094877cdcc50e3da
3
+ metadata.gz: 8967f465fedf7db2ebaed2f024a942ed580d4ace8fac502a8a144d9720685d99
4
+ data.tar.gz: 708184decf1b1f474735792e53c4ec529a3317e3b824c2a7889b26f2eb0e6884
5
5
  SHA512:
6
- metadata.gz: 0c8b3606430fa433bac4af10b1946bfa1c3690d9010fb3a013e5aaec49876a879eaaa3aebbe3719c9e8f2155ec5cc0ae640a88e830189fc35746614b41af96b2
7
- data.tar.gz: 743aeeffc4604c367940f3e6b38aecf66bed583f91c63a6406d22c4d070982d7569c25feaa379b7ba1e1568a6b18625d5fd401cc6bde1ceace5648a8769c0bd6
6
+ metadata.gz: 7e9bcf100b39f8f84363f9932b9785f6d208e16af94b455991eff8eb5092350de31457368769f496c71837381bf7749d9e15f61001d8bcf43aa430a635482a72
7
+ data.tar.gz: 7b4052eb2852bd40cc9aefed3afeb398b6b5e832f4a1aa66d77342eca8439170b3737e4d0df2f571e1ce085d512a8437ca4de90d049fa7e0cfaf28935c308e15
@@ -0,0 +1,26 @@
1
+ module ActiveModel
2
+ module Type
3
+ class Enum < ActiveModel::Type::Value
4
+ def initialize(enum_class)
5
+ @enum_class = enum_class
6
+ super()
7
+ end
8
+
9
+ def cast(value)
10
+ value.is_a?(@enum_class) ? value : @enum_class.find_by_key(value&.to_sym)
11
+ end
12
+
13
+ def serialize(value)
14
+ value.is_a?(@enum_class) ? value.key : value&.to_s
15
+ end
16
+
17
+ def deserialize(value)
18
+ value.is_a?(@enum_class) ? value : @enum_class.find_by_key(value&.to_sym)
19
+ end
20
+
21
+ def type
22
+ :enum
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/enumy/base.rb CHANGED
@@ -5,27 +5,34 @@ module Enumy
5
5
  include ActiveModel::Model
6
6
  include ActiveModel::Attributes
7
7
 
8
- attribute :id
9
- attribute :name
8
+ attribute :key
10
9
 
11
- def initialize(id, name, **attrs)
12
- raise ArgumentError, "#{self.class.name.upcase} enum requires an `id`" if id.nil?
13
- raise ArgumentError, "#{self.class.name.upcase} enum requires a `name`" if name.nil?
10
+ def initialize(key, **attrs)
11
+ raise ArgumentError, "#{self.class.name.upcase} enum requires a `key`" if key.nil?
12
+ key = key.to_sym
14
13
 
15
- super(id: id, name: name, **attrs)
14
+ super(key: key, **attrs)
16
15
  end
17
16
 
18
17
  def human_attribute_name(attribute)
19
- I18n.t("#{self.class.i18n_scope}.attributes.models.#{self.class.model_name.i18n_key}/#{self.name}.#{attribute}")
18
+ I18n.t("#{self.class.i18n_scope}.attributes.models.#{self.class.model_name.i18n_key}/#{self.key}.#{attribute}")
19
+ end
20
+
21
+ def to_s
22
+ self.key.to_s
23
+ end
24
+
25
+ def inspect
26
+ "#<#{self.class.name} #{attributes.map { |name, value| "#{name}: #{value.inspect}" }.join(', ')}>"
20
27
  end
21
28
 
22
29
  class << self
23
30
 
24
- def register(enum)
25
- if instances[enum.id]
26
- raise ArgumentError, "Enum `#{enum.name.to_s.upcase}` is using a duplicate id `#{enum.id}` for Enum '#{enum.class.name}'."
31
+ def define(enum)
32
+ if instances[enum.key]
33
+ raise ArgumentError, "Enum `#{enum.key.to_s.upcase}` is using a duplicate key `#{enum.key}` for Enum '#{enum.class.name}'."
27
34
  else
28
- instances[enum.id] = enum
35
+ instances[enum.key] = enum
29
36
  end
30
37
  end
31
38
 
@@ -33,12 +40,12 @@ module Enumy
33
40
  instances.values
34
41
  end
35
42
 
36
- def find(id)
37
- find_by_id(id) || raise(Errors::EnumNotFoundError.new("Could not find a `#{name}` enum with an `id` of #{id}"))
43
+ def find(key)
44
+ find_by_key(key) || raise(Errors::EnumNotFoundError.new("Could not find a `#{self.name}` enum with a `key` of #{key}"))
38
45
  end
39
46
 
40
- def find_by_id(id)
41
- instances[id]
47
+ def find_by_key(key)
48
+ instances[key]
42
49
  end
43
50
 
44
51
  def find_by(**args)
@@ -48,7 +55,7 @@ module Enumy
48
55
  end
49
56
 
50
57
  def model_name
51
- @model_name ||= ActiveModel::Name.new(self, nil, name.to_s)
58
+ @model_name ||= ActiveModel::Name.new(self, nil, self.name.to_s)
52
59
  end
53
60
 
54
61
  def i18n_scope
data/lib/enumy/model.rb CHANGED
@@ -3,48 +3,30 @@ require_relative 'errors'
3
3
 
4
4
  module Enumy
5
5
  module Model
6
- def belongs_to_enum(name, class_name: name, default: nil)
6
+ def has_enum(name, class_name: name, **options)
7
7
  enum_class = class_name.to_s.classify.safe_constantize
8
-
9
- if enum_class.nil?
10
- raise Errors::InvalidEnumClassError, "Could not resolve class `#{class_name.to_s.classify}`"
11
- elsif !enum_class.ancestors.include?(Enumy::Base)
12
- raise Errors::InvalidEnumClassError, "`#{enum_class.name}` does not inherit from `Enumy::Base`"
13
- end
14
-
15
- define_method "#{name}=" do |enum|
16
- raise NameError, "Enum `#{enum_class.name}` expected #{self.class.name} to have attribute `#{name}_id`." unless self.has_attribute?("#{name}_id")
17
8
 
18
- if enum
19
- raise Errors::InvalidEnumClassError, "Expected an enum of type `#{enum_class.name}`, got `#{enum.class.name}`" if enum_class != enum.class
20
- self.send("#{name}_id=", enum.id)
21
- else
22
- self.send("#{name}_id=", nil)
23
- end
24
-
25
- instance_variable_set("@#{name}", enum)
26
- end
9
+ assert_valid_enum_type!(enum_class)
10
+ define_enum_attributes(name, enum_class, default: options[:default])
11
+ define_enum_validations(name, enum_class) unless options[:optional]
12
+ end
27
13
 
28
- define_method "#{name}" do
29
- enum = instance_variable_get("@#{name}")
30
- return enum if enum
14
+ private
31
15
 
32
- raise NameError, "Enum `#{enum_class.name}` expected #{self.class.name} to have attribute `#{name}_id`." unless self.has_attribute?("#{name}_id")
33
- return nil unless self.send("#{name}_id")
34
- instance_variable_set("@#{name}", enum_class.find(self.send("#{name}_id")))
35
- end
16
+ def define_enum_attributes(name, enum_class, **options)
17
+ attribute name, ActiveModel::Type::Enum.new(enum_class), default: -> { options[:default] }
18
+ end
36
19
 
37
- define_method "#{name}_id=" do |new_id|
38
- super(new_id)
20
+ def define_enum_validations(name, enum_class)
21
+ validates name, presence: true, inclusion: { in: enum_class.all }
22
+ end
39
23
 
40
- if new_id
41
- instance_variable_set("@#{name}", enum_class.find(new_id))
42
- else
43
- instance_variable_set("@#{name}", nil)
44
- end
24
+ def assert_valid_enum_type!(enum_class)
25
+ if enum_class.nil?
26
+ raise Errors::InvalidEnumClassError, "Could not resolve class `#{enum_class.name.to_s.classify}`"
27
+ elsif !enum_class.ancestors.include?(Enumy::Base)
28
+ raise Errors::InvalidEnumClassError, "`#{enum_class.name}` does not inherit from `#{Enumy::Base.name}`"
45
29
  end
46
-
47
- after_initialize -> { self.send("#{name}=", default) if self.has_attribute?("#{name}_id") && self.send("#{name}").nil? && default.present? }
48
30
  end
49
31
  end
50
32
  end
data/lib/enumy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Enumy
4
- VERSION = "0.1.5"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/enumy.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  require 'enumy/base'
2
2
  require 'enumy/model'
3
3
  require 'generators/enumy/install/install_generator'
4
+ require 'active_model/type/enum'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enumy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bevan Holborn
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-14 00:00:00.000000000 Z
10
+ date: 2025-03-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rake
@@ -42,6 +42,7 @@ executables: []
42
42
  extensions: []
43
43
  extra_rdoc_files: []
44
44
  files:
45
+ - lib/active_model/type/enum.rb
45
46
  - lib/enumy.rb
46
47
  - lib/enumy/base.rb
47
48
  - lib/enumy/errors.rb