minenum 0.1.0 → 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: 62775a6aa94437fc897c0ced4c9f7209cd279ab4c51f55793c3dbd218a4cf492
4
- data.tar.gz: 5fd974a1b3efb463a6b39aea2a5206c7acc013c729acdc80a590e0e6b1011e3c
3
+ metadata.gz: e30a7b63806d1b89941d7297d647ff2c023ec029f703e4522d4575f4bffa356e
4
+ data.tar.gz: 627051960b7b12cb639b4a11255bb570037dfa1c427ff2ea80ca4f5ef047a416
5
5
  SHA512:
6
- metadata.gz: 8c75161d38a61f3e67c83f7ade775ea3c9de48fc9f1a90f991c77835f6469be11bd3bbbf947a3fe7cd5d375ada00d8a56be320565c6516eb4fd62bf31d25f912
7
- data.tar.gz: 9706434cf641116c550cc341686059721495ec9dcb9528077562fccd90e5f08ea6f45fd7dc39caaa0990a74282b06accd63e48052fb03181b6f5f76a06cfd705
6
+ metadata.gz: 2b8856a071493ce14759178492992bf0578e75a71b6d10d992573caba2979b8d3027fd7b1a80f34639e598f575479ee776dfd39c5c28fefdd67003d6f94679a8
7
+ data.tar.gz: 6eddef5145f0b90c81d0a188a62dbad5fb171f9cb5b21adcc0ab854fba993e35306c498ffad9955f912d84cdace9fc55849a78076beb381377fbd2ebd8f5bff9
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Maintainability](https://api.codeclimate.com/v1/badges/04440479daa0ecea68de/maintainability)](https://codeclimate.com/github/nowlinuxing/minenum/maintainability)
2
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/04440479daa0ecea68de/test_coverage)](https://codeclimate.com/github/nowlinuxing/minenum/test_coverage)
3
+
1
4
  # Minenum
2
5
 
3
6
  Minenum is a gem that enhances Ruby objects by adding enum functionality and returning enum objects as return values. Enums simplify representing states or types within a specific range of values and can be returned directly from methods.
@@ -37,6 +40,10 @@ shirt.size.small? #=> true
37
40
  shirt.size = :medium
38
41
  shirt.size.name #=> :medium
39
42
  shirt.size.medium? #=> true
43
+
44
+ # Call bang method to change the enum value
45
+ shirt.size.small!
46
+ shirt.size.small? #=> true
40
47
  ```
41
48
 
42
49
  ```ruby
data/Steepfile CHANGED
@@ -6,4 +6,5 @@ target :lib do
6
6
  signature 'sig'
7
7
 
8
8
  check 'lib'
9
+ library 'forwardable'
9
10
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Minenum
4
+ module Enum
5
+ module Adapter
6
+ class Base # :nodoc:
7
+ def self.build(enum_object, name)
8
+ new(enum_object, name)
9
+ end
10
+
11
+ def initialize(enum_object, name)
12
+ @enum_object = enum_object
13
+ @name = name
14
+ end
15
+
16
+ def get
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def set(_value)
21
+ raise NotImplementedError
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Minenum
6
+ module Enum
7
+ module Adapter
8
+ class LocalInstanceVariableAccessor < Base # :nodoc:
9
+ def initialize(enum_object = nil, name = nil)
10
+ super
11
+ @value = nil
12
+ end
13
+
14
+ def get
15
+ @value
16
+ end
17
+
18
+ def set(value)
19
+ @value = value
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,13 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+ require_relative 'adapter/local_instance_variable_accessor'
5
+
3
6
  module Minenum
4
7
  module Enum
5
8
  class Base # :nodoc:
6
- attr_reader :value
9
+ extend Forwardable
10
+
11
+ singleton_class.attr_reader :_values
12
+
13
+ alias _inspect inspect
14
+ def_delegators :name, :to_s, :to_sym, :inspect, :pretty_print
15
+
16
+ def self.values
17
+ _values.values
18
+ end
19
+
20
+ def initialize(adapter = Adapter::LocalInstanceVariableAccessor.new)
21
+ @adapter = adapter
22
+ end
23
+
24
+ def name
25
+ self.class._values.key(_raw_value)
26
+ end
27
+
28
+ def value
29
+ self.class._values.value(_raw_value)
30
+ end
31
+
32
+ def value=(value)
33
+ @adapter.set(self.class._values.value(value))
34
+ end
35
+
36
+ private
7
37
 
8
- def initialize(value)
9
- @value = value
10
- freeze
38
+ def _raw_value
39
+ @adapter.get
11
40
  end
12
41
  end
13
42
  end
@@ -17,34 +17,34 @@ module Minenum
17
17
  def build
18
18
  values = Values.new(@values)
19
19
 
20
- klass = Class.new(Base)
21
- add_values_method(klass, values)
22
- add_name_method(klass, values)
23
- add_predicate_methods(klass, values)
20
+ klass = Class.new(Base) do
21
+ @_values = values
22
+ end
23
+
24
+ values.each_key do |key|
25
+ add_predicate_method(klass, key)
26
+ add_bang_method(klass, key)
27
+ end
24
28
 
25
29
  klass
26
30
  end
27
31
 
28
32
  private
29
33
 
30
- def add_values_method(klass, values)
31
- klass.singleton_class.define_method(:values) do
32
- values.values
33
- end
34
- end
35
-
36
- def add_name_method(klass, values)
37
- klass.define_method(:name) do
38
- values.key(@value)
39
- end
34
+ def add_predicate_method(klass, key)
35
+ klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
36
+ def #{key}? # def small?
37
+ self.class._values.match?(:'#{key}', value) # self.class._values.match?(:'small', value)
38
+ end # end
39
+ RUBY
40
40
  end
41
41
 
42
- def add_predicate_methods(klass, values)
43
- values.each_key do |key|
44
- klass.define_method("#{key}?") do
45
- values.match?(key, @value)
46
- end
47
- end
42
+ def add_bang_method(klass, key)
43
+ klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
44
+ def #{key}! # def small!
45
+ self.value = :'#{key}' # self.value = :'small'
46
+ end # end
47
+ RUBY
48
48
  end
49
49
  end
50
50
  end
@@ -6,7 +6,7 @@ module Minenum
6
6
  attr_reader :values
7
7
 
8
8
  def initialize(values)
9
- @values = values.transform_keys(&:to_sym).tap(&:freeze)
9
+ @values = values.transform_keys(&:to_sym).transform_values(&:freeze).tap(&:freeze)
10
10
  freeze
11
11
  end
12
12
 
@@ -15,37 +15,52 @@ module Minenum
15
15
  end
16
16
 
17
17
  def key(key_or_value)
18
- if key_or_value.respond_to?(:to_sym) && (key_sym = key_or_value.to_sym) && @values.key?(key_sym)
19
- key_sym
20
- else
21
- return @values.key(key_or_value) if @values.value?(key_or_value)
18
+ return key_or_value if @values.key?(key_or_value)
19
+ return @values.key(key_or_value) if @values.value?(key_or_value)
22
20
 
23
- case key_or_value
24
- when Symbol then @values.key(key_or_value.to_s)
25
- when String then @values.key(key_or_value.to_sym)
26
- end
27
- end
21
+ return key_or_value.to_sym if match_as_key?(key_or_value)
22
+
23
+ find_by_key(key_or_value)
24
+ end
25
+
26
+ def value(key_or_value)
27
+ return @values.values.find { _1 == key_or_value } if @values.value?(key_or_value)
28
+ return @values[key_or_value] if @values.key?(key_or_value)
29
+
30
+ val = find_by_value(key_or_value)
31
+ return val if val
32
+
33
+ @values[key_or_value.to_sym] if match_as_key?(key_or_value)
28
34
  end
29
35
 
30
36
  def match?(key_name, key_or_value)
31
- if key_or_value.respond_to?(:to_sym) && (key_sym = key_or_value.to_sym) && @values.key?(key_sym)
32
- key_sym == key_name.to_sym
33
- else
34
- match_with_value?(key_name, key_or_value)
35
- end
37
+ key(key_or_value) == key_name.to_sym
36
38
  end
37
39
 
38
40
  private
39
41
 
40
- def match_with_value?(key_name, value)
41
- registered_value = @values[key_name.to_sym]
42
- return true if value == registered_value
42
+ def match_as_key?(key_or_value)
43
+ return false unless key_or_value.respond_to?(:to_sym)
44
+
45
+ @values.key?(key_or_value.to_sym)
46
+ end
47
+
48
+ def find_by_key(key_or_value)
49
+ case key_or_value
50
+ when Symbol then @values.key(key_or_value.to_s)
51
+ when String then @values.key(key_or_value.to_sym)
52
+ end
53
+ end
43
54
 
44
- case value
45
- when Symbol then value.to_s == registered_value
46
- when String then value.to_sym == registered_value
47
- else false
55
+ def find_by_value(key_or_value)
56
+ case key_or_value
57
+ when Symbol then value = key_or_value.to_s
58
+ when String then value = key_or_value.to_sym
59
+ else
60
+ return
48
61
  end
62
+
63
+ @values.values.find { _1 == value }
49
64
  end
50
65
  end
51
66
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../enum/class_builder'
4
+ require_relative '../enum/adapter/local_instance_variable_accessor'
5
+
6
+ module Minenum
7
+ module Model
8
+ class Reflection # :nodoc:
9
+ attr_reader :adapter_builder
10
+
11
+ def initialize(owner_class, name, values, adapter_builder: Enum::Adapter::LocalInstanceVariableAccessor)
12
+ @owner_class = owner_class
13
+ @name = name
14
+ @values = values
15
+
16
+ @adapter_builder = adapter_builder
17
+ end
18
+
19
+ def name
20
+ @name.to_sym
21
+ end
22
+
23
+ def enum_class
24
+ @enum_class ||= begin
25
+ basename = classify(@name.to_s)
26
+
27
+ if @owner_class.const_defined?(basename, false)
28
+ @owner_class.const_get(basename, false)
29
+ else
30
+ klass = Enum::ClassBuilder.build(@values)
31
+ @owner_class.const_set(basename, klass)
32
+ end
33
+ end
34
+ end
35
+
36
+ def build_enum(model)
37
+ adapter = @adapter_builder.build(model, @name)
38
+ enum_class.new(adapter)
39
+ end
40
+
41
+ private
42
+
43
+ def classify(key)
44
+ key.gsub(/([a-z\d]+)_?/) { ::Regexp.last_match(1)&.capitalize }
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/minenum/model.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'enum'
4
+ require_relative 'enum/adapter/local_instance_variable_accessor'
5
+ require_relative 'model/reflection'
4
6
 
5
7
  module Minenum
6
8
  # = Minenum
@@ -27,42 +29,56 @@ module Minenum
27
29
  # Shirt.size.values #=> { small: 1, medium: 2, large: 3 }
28
30
  #
29
31
  module Model
30
- module InstanceVariableAccessor # :nodoc:
31
- def set(model, name, value)
32
- enum = if model.instance_variable_defined?(:@_minenum_enum)
33
- model.instance_variable_get(:@_minenum_enum)
34
- else
35
- model.instance_variable_set(:@_minenum_enum, {})
36
- end
37
- enum[name] = value
32
+ def self.included(base)
33
+ base.extend ClassMethods
34
+ base.include InstanceMethods
35
+ end
36
+
37
+ module AccessorAdder # :nodoc:
38
+ def add(model_class, methods_module, reflection)
39
+ add_singleton_method(model_class, reflection.name)
40
+
41
+ add_getter(methods_module, reflection.name)
42
+ add_setter(methods_module, reflection.name)
43
+
44
+ model_class._minenum_reflections[reflection.name] = reflection
38
45
  end
39
- module_function :set
46
+ module_function :add
40
47
 
41
- def get(model, name)
42
- enum = model.instance_variable_get(:@_minenum_enum)
43
- enum&.[](name)
48
+ def add_singleton_method(model_class, name)
49
+ model_class.class_eval <<~RUBY, __FILE__, __LINE__ + 1
50
+ def self.#{name} # def self.size
51
+ _minenum_reflections[:'#{name}'].enum_class # _minenum_reflections[:'size'].enum_class
52
+ end # end
53
+ RUBY
44
54
  end
45
- module_function :get
46
- end
47
55
 
48
- def self.included(base)
49
- base.extend ClassMethods
56
+ def add_getter(methods_module, name)
57
+ methods_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
58
+ def #{name} # def size
59
+ _minenum_enum(:'#{name}') # _minenum_enum(:'size')
60
+ end # end
61
+ RUBY
62
+ end
63
+
64
+ def add_setter(methods_module, name)
65
+ methods_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
66
+ def #{name}=(value) # def size=(value)
67
+ _minenum_enum(:'#{name}').value = value # _minenum_enum(:'size').value = value
68
+ end # end
69
+ RUBY
70
+ end
71
+ module_function :add_singleton_method, :add_getter, :add_setter
50
72
  end
51
73
 
52
74
  module ClassMethods # :nodoc:
53
- def enum(name, values, adapter: InstanceVariableAccessor)
54
- enum_class = Enum::ClassBuilder.build(values)
55
-
56
- const_set(classify(name.to_s), enum_class)
57
- singleton_class.define_method(name) { enum_class }
58
-
59
- enum_methods_module.define_method("#{name}=") do |value|
60
- adapter.set(self, name, value)
61
- end
75
+ def enum(name, values, adapter_builder: Enum::Adapter::LocalInstanceVariableAccessor)
76
+ reflection = Reflection.new(self, name, values, adapter_builder: adapter_builder)
77
+ AccessorAdder.add(self, enum_methods_module, reflection)
78
+ end
62
79
 
63
- enum_methods_module.define_method(name) do
64
- enum_class.new(adapter.get(self, name))
65
- end
80
+ def _minenum_reflections
81
+ @_minenum_reflections ||= {}
66
82
  end
67
83
 
68
84
  private
@@ -74,9 +90,14 @@ module Minenum
74
90
  mod
75
91
  end
76
92
  end
93
+ end
94
+
95
+ module InstanceMethods # :nodoc:
96
+ private
77
97
 
78
- def classify(key)
79
- key.gsub(/([a-z\d]+)_?/) { ::Regexp.last_match(1)&.capitalize }
98
+ def _minenum_enum(name)
99
+ @_minenum_enum ||= {}
100
+ @_minenum_enum[name.to_sym] ||= self.class._minenum_reflections[name.to_sym].build_enum(self)
80
101
  end
81
102
  end
82
103
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Minenum
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -0,0 +1,24 @@
1
+ module Minenum
2
+ module Enum
3
+ module Adapter
4
+ interface _AdapterBuilder
5
+ def build: (untyped, Symbol) -> Minenum::Enum::Adapter::Base
6
+ end
7
+
8
+ interface _Adapter
9
+ def get: -> untyped
10
+ def set: (untyped) -> untyped
11
+ end
12
+
13
+ class Base
14
+ extend _AdapterBuilder
15
+ include _Adapter
16
+
17
+ @enum_object: untyped
18
+ @name: String | Symbol
19
+
20
+ def initialize: (untyped, Symbol) -> void
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module Minenum
2
+ module Enum
3
+ module Adapter
4
+ class LocalInstanceVariableAccessor
5
+ include Minenum::Enum::Adapter::_Adapter
6
+
7
+ @value: untyped
8
+
9
+ def initialize: (?untyped, ?Symbol) -> void
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,9 +1,24 @@
1
1
  module Minenum
2
2
  module Enum
3
3
  class Base
4
- attr_reader value: untyped
4
+ extend Forwardable
5
+
6
+ @adapter: Minenum::Enum::Adapter::_Adapter
7
+
8
+ attr_reader self._values: Minenum::Enum::Values
9
+
10
+ alias _inspect inspect
11
+
12
+ def self.values: -> Hash[Symbol, untyped]
5
13
 
6
14
  def initialize: (untyped) -> void
15
+ def name: -> Symbol?
16
+ def value: -> untyped
17
+ def value=: (untyped) -> untyped
18
+
19
+ private
20
+
21
+ def _raw_value: -> untyped
7
22
  end
8
23
  end
9
24
  end
@@ -11,9 +11,8 @@ module Minenum
11
11
 
12
12
  private
13
13
 
14
- def add_values_method: (untyped, Minenum::Enum::Values) -> void
15
- def add_name_method: (untyped, Minenum::Enum::Values) -> void
16
- def add_predicate_methods: (untyped, Minenum::Enum::Values) -> void
14
+ def add_predicate_method: (untyped, Symbol) -> void
15
+ def add_bang_method: (untyped, Symbol) -> void
17
16
  end
18
17
  end
19
18
  end
@@ -1,16 +1,21 @@
1
1
  module Minenum
2
2
  module Enum
3
3
  class Values
4
+ @values: Hash[Symbol, untyped]
5
+
4
6
  attr_reader values: Hash[Symbol, untyped]
5
7
 
6
8
  def initialize: (Hash[String | Symbol, untyped]) -> void
7
9
  def each_key: { (Symbol) -> untyped } -> Hash[String | Symbol, untyped]
8
10
  def key: (untyped) -> Symbol?
11
+ def value: (untyped) -> untyped
9
12
  def match?: (String | Symbol, untyped) -> bool
10
13
 
11
14
  private
12
15
 
13
- def match_with_value?: (String | Symbol, untyped) -> bool
16
+ def match_as_key?: (untyped) -> bool
17
+ def find_by_key: (untyped) -> Symbol?
18
+ def find_by_value: (untyped) -> untyped
14
19
  end
15
20
  end
16
21
  end
@@ -0,0 +1,22 @@
1
+ module Minenum
2
+ module Model
3
+ class Reflection
4
+ @owner_class: untyped
5
+ @name: Symbol | String
6
+ @values: Hash[untyped, untyped]
7
+ @adapter: untyped
8
+ @enum_class: Minenum::Enum::Base
9
+
10
+ attr_reader adapter_builder: untyped
11
+
12
+ def initialize: (untyped, String | Symbol, Hash[untyped, untyped], ?adapter_builder: Minenum::Enum::Adapter::_AdapterBuilder) -> void
13
+ def name: -> Symbol
14
+ def enum_class: -> untyped
15
+ def build_enum: (untyped) -> untyped
16
+
17
+ private
18
+
19
+ def classify: (String) -> String
20
+ end
21
+ end
22
+ end
@@ -1,24 +1,29 @@
1
1
  module Minenum
2
2
  module Model
3
- interface _Accessor
4
- def set: (untyped model, String | Symbol name, untyped value) -> untyped
5
- def get: (untyped model, String | Symbol name) -> untyped
6
- end
7
-
8
- module InstanceVariableAccessor
9
- include _Accessor
3
+ module AccessorAdder
4
+ def self?.add: (untyped, untyped, Minenum::Model::Reflection) -> void
5
+ def self?.add_singleton_method: (untyped, Symbol) -> void
6
+ def self?.add_getter: (untyped, Symbol) -> void
7
+ def self?.add_setter: (untyped, Symbol) -> void
10
8
  end
11
9
 
12
10
  module ClassMethods
13
- def enum: (String | Symbol name, Hash[String | Symbol, untyped], ?adapter: _Accessor) -> void
11
+ def enum: (String | Symbol name, Hash[String | Symbol, untyped], ?adapter_builder: Minenum::Enum::Adapter::_AdapterBuilder) -> void
12
+ def _minenum_reflections: -> Hash[Symbol, untyped]
14
13
 
15
14
  private
16
15
 
17
16
  def enum_methods_module: -> Module
18
- def classify: (String) -> String
19
17
 
20
- def const_set: [T] (String | Symbol, T) -> T
21
18
  def include: (Module) -> self
22
19
  end
20
+
21
+ module InstanceMethods
22
+ private
23
+
24
+ def _minenum_enum: (Symbol) -> untyped
25
+
26
+ def self._minenum_reflections: -> Hash[Symbol, untyped]
27
+ end
23
28
  end
24
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minenum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loose Coupling
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-22 00:00:00.000000000 Z
11
+ date: 2024-06-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Enum for Ruby
14
14
  email:
@@ -26,17 +26,23 @@ files:
26
26
  - Steepfile
27
27
  - lib/minenum.rb
28
28
  - lib/minenum/enum.rb
29
+ - lib/minenum/enum/adapter/base.rb
30
+ - lib/minenum/enum/adapter/local_instance_variable_accessor.rb
29
31
  - lib/minenum/enum/base.rb
30
32
  - lib/minenum/enum/class_builder.rb
31
33
  - lib/minenum/enum/values.rb
32
34
  - lib/minenum/model.rb
35
+ - lib/minenum/model/reflection.rb
33
36
  - lib/minenum/version.rb
34
37
  - minenum.gemspec
35
38
  - sig/minenum.rbs
39
+ - sig/minenum/enum/adapter/base.rbs
40
+ - sig/minenum/enum/adapter/local_instance_variable_accessor.rbs
36
41
  - sig/minenum/enum/base.rbs
37
42
  - sig/minenum/enum/class_builder.rbs
38
43
  - sig/minenum/enum/values.rbs
39
44
  - sig/minenum/model.rbs
45
+ - sig/minenum/model/reflection.rbs
40
46
  homepage: https://github.com/nowlinuxing/minenum
41
47
  licenses:
42
48
  - MIT
@@ -60,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
66
  - !ruby/object:Gem::Version
61
67
  version: '0'
62
68
  requirements: []
63
- rubygems_version: 3.5.3
69
+ rubygems_version: 3.5.9
64
70
  signing_key:
65
71
  specification_version: 4
66
72
  summary: Enum for Ruby