smart_initializer 0.7.0 → 0.8.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +35 -3
  4. data/Gemfile.lock +38 -38
  5. data/README.md +260 -46
  6. data/bin/console +2 -2
  7. data/gemfiles/with_external_deps.gemfile.lock +38 -38
  8. data/lib/smart_core/initializer/attribute/factory/base.rb +145 -0
  9. data/lib/smart_core/initializer/attribute/factory/option.rb +107 -0
  10. data/lib/smart_core/initializer/attribute/factory/param.rb +63 -0
  11. data/lib/smart_core/initializer/attribute/factory.rb +5 -199
  12. data/lib/smart_core/initializer/attribute/finalizer/abstract.rb +2 -0
  13. data/lib/smart_core/initializer/attribute/finalizer/instance_method.rb +1 -1
  14. data/lib/smart_core/initializer/attribute/finalizer.rb +5 -5
  15. data/lib/smart_core/initializer/attribute/list.rb +20 -0
  16. data/lib/smart_core/initializer/attribute/{parameters.rb → value/base.rb} +35 -65
  17. data/lib/smart_core/initializer/attribute/value/option.rb +101 -0
  18. data/lib/smart_core/initializer/attribute/value/param.rb +24 -0
  19. data/lib/smart_core/initializer/attribute/value.rb +9 -0
  20. data/lib/smart_core/initializer/attribute.rb +3 -125
  21. data/lib/smart_core/initializer/configuration.rb +7 -3
  22. data/lib/smart_core/initializer/constructor/definer.rb +135 -46
  23. data/lib/smart_core/initializer/constructor.rb +30 -12
  24. data/lib/smart_core/initializer/dsl.rb +38 -24
  25. data/lib/smart_core/initializer/errors.rb +20 -4
  26. data/lib/smart_core/initializer/functionality.rb +7 -8
  27. data/lib/smart_core/initializer/settings/auto_cast.rb +40 -0
  28. data/lib/smart_core/initializer/settings/base.rb +49 -0
  29. data/lib/smart_core/initializer/settings/duplicator.rb +5 -0
  30. data/lib/smart_core/initializer/settings/strict_options.rb +40 -0
  31. data/lib/smart_core/initializer/settings/type_system.rb +10 -28
  32. data/lib/smart_core/initializer/settings.rb +40 -0
  33. data/lib/smart_core/initializer/type_system/registry.rb +2 -1
  34. data/lib/smart_core/initializer/type_system/smart_types.rb +2 -2
  35. data/lib/smart_core/initializer/version.rb +2 -2
  36. data/lib/smart_core/initializer.rb +14 -4
  37. data/smart_initializer.gemspec +2 -2
  38. metadata +16 -7
@@ -14,6 +14,7 @@ module SmartCore::Initializer::Attribute::Finalizer
14
14
  #
15
15
  # @api private
16
16
  # @since 0.1.0
17
+ # @version 0.8.0
17
18
  def create(finalization_approach)
18
19
  case finalization_approach
19
20
  when String, Symbol
@@ -21,11 +22,10 @@ module SmartCore::Initializer::Attribute::Finalizer
21
22
  when Proc
22
23
  AnonymousBlock.new(finalization_approach)
23
24
  else
24
- # :nocov:
25
- raise(SmartCore::Initializer::ArgumentError, <<~ERROR_MESSAGE)
26
- Finalization approach should be a type of Proc, Symbol or String'
27
- ERROR_MESSAGE
28
- # :nocov:
25
+ raise(
26
+ SmartCore::Initializer::ArgumentError,
27
+ 'Finalization approach object should be a type of Proc, Symbol or String'
28
+ )
29
29
  end
30
30
  end
31
31
  end
@@ -15,6 +15,26 @@ class SmartCore::Initializer::Attribute::List
15
15
  @lock = SmartCore::Engine::Lock.new
16
16
  end
17
17
 
18
+ # @param attribute_name [Symbol]
19
+ # @return [SmartCore::Initializer::Atribute]
20
+ #
21
+ # @raise [SmartCore::Initializer::UndefinedAttributeError]
22
+ #
23
+ # @api private
24
+ # @since 0.8.0
25
+ def fetch(attribute_name)
26
+ thread_safe do
27
+ attributes.fetch(attribute_name)
28
+ rescue ::KeyError
29
+ raise(
30
+ ::SmartCore::Initializer::UndefinedAttributeError,
31
+ "Attribute with `#{attribute_name}` name is not defined in your constructor. " \
32
+ "Please, check your attribute definitions inside your class."
33
+ )
34
+ end
35
+ end
36
+ alias_method :[], :fetch
37
+
18
38
  # @param attribute [SmartCore::Initializer::Attribute]
19
39
  # @return [void]
20
40
  #
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api private
4
- # @since 0.1.0
5
- class SmartCore::Initializer::Attribute::Parameters
4
+ # @since 0.8.0
5
+ class SmartCore::Initializer::Attribute::Value::Base
6
6
  # @return [Hash<Symbol,Symbol>]
7
7
  #
8
8
  # @api private
9
- # @since 0.1.0
9
+ # @since 0.8.0
10
10
  PRIVACY_MODES = {
11
11
  public: :public,
12
12
  protected: :protected,
@@ -16,93 +16,76 @@ class SmartCore::Initializer::Attribute::Parameters
16
16
  # @return [Symbol]
17
17
  #
18
18
  # @api private
19
- # @since 0.1.0
19
+ # @since 0.8.0
20
20
  DEFAULT_PRIVACY_MODE = PRIVACY_MODES[:public]
21
21
 
22
- # @return [Boolean]
23
- #
24
- # @api private
25
- # @since 0.1.0
26
- DEFAULT_CAST_BEHAVIOUR = false
27
-
28
22
  # @return [Proc]
29
23
  #
30
24
  # @api private
31
- # @since 0.1.0
25
+ # @since 0.8.0
32
26
  DEFAULT_FINALIZER = proc { |value| value }.freeze
33
27
 
34
- # @return [Hash]
28
+ # @return [NilClass]
35
29
  #
36
30
  # @api private
37
- # @since 0.1.0
38
- DEFAULT_DYNAMIC_OPTIONS = {}.freeze
31
+ # @since 0.8.0
32
+ DEFAULT_AS = nil
39
33
 
40
34
  # @return [Boolean]
41
35
  #
42
36
  # @api private
43
- # @since 0.4.0
44
- DEFAULT_READ_ONLY = true
45
-
46
- # @return [NilClass]
47
- #
48
- # @api private
49
- # @since 0.4.0
50
- DEFAULT_AS = nil
37
+ # @since 0.8.0
38
+ DEFAULT_MUTABLE = false
51
39
 
52
40
  # @return [Symbol]
53
41
  #
54
42
  # @api private
55
- # @since 0.1.0
43
+ # @since 0.8.0
56
44
  attr_reader :name
57
45
 
58
46
  # @return [SmartCore::Initializer::TypeSystem::Interop]
59
47
  #
60
48
  # @api private
61
- # @since 0.1.0
49
+ # @since 0.8.0
62
50
  attr_reader :type
63
51
 
64
52
  # @return [Class<SmartCore::Initilizer::TypeSystem::Interop>]
65
53
  #
66
54
  # @api private
67
- # @since 0.1.0
55
+ # @since 0.8.0
68
56
  attr_reader :type_system
69
57
 
70
58
  # @return [Symbol]
71
59
  #
72
60
  # @api private
73
- # @since 0.1.0
61
+ # @since 0.8.0
74
62
  attr_reader :privacy
75
63
 
76
64
  # @return [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock]
77
65
  # @return [SmartCore::Initializer::Attribute::Finalizer::InstanceMethod]
78
66
  #
79
67
  # @api private
80
- # @since 0.1.0
68
+ # @since 0.8.0
81
69
  attr_reader :finalizer
82
70
 
83
71
  # @return [Boolean]
84
72
  #
85
73
  # @api private
86
- # @since 0.1.0
74
+ # @since 0.8.0
87
75
  attr_reader :cast
88
76
  alias_method :cast?, :cast
89
77
 
90
- # @return [Hash<Symbol,Any>]
91
- #
92
- # @api private
93
- # @since 0.1.0
94
- attr_reader :dynamic_options
95
-
96
78
  # @return [Boolean]
97
79
  #
98
80
  # @api private
99
- # @since 0.4.0
100
- attr_reader :read_only
81
+ # @since 0.8.0
82
+ attr_reader :mutable
83
+ alias_method :mutable?, :mutable
101
84
 
102
85
  # @return [String, Symbol, NilClass]
103
86
  #
104
87
  # @api private
105
- # @since 0.4.0
88
+ # @since 0.8.0
106
89
  attr_reader :as
107
90
 
108
91
  # @param name [Symbol]
@@ -111,48 +94,35 @@ class SmartCore::Initializer::Attribute::Parameters
111
94
  # @param privacy [Symbol]
112
95
  # @param finalizer [SmartCore::Initializer::Attribute::AnonymousBlock/InstanceMethod]
113
96
  # @param cast [Boolean]
114
- # @param read_only [Boolean]
97
+ # @param mutable [Boolean]
115
98
  # @param as [NilClass, Symbol, String]
116
- # @param dynamic_options [Hash<Symbol,Any>]
117
- # - :default - default value (Proc value will be called)
118
99
  # @return [void]
119
100
  #
120
101
  # @api private
121
- # @since 0.1.0
122
- # @version 0.4.0
123
- def initialize(name, type, type_system, privacy, finalizer, cast, read_only, as, dynamic_options)
102
+ # @since 0.8.0
103
+ def initialize(name, type, type_system, privacy, finalizer, cast, mutable, as)
124
104
  @name = name
125
105
  @type = type
126
106
  @type_system = type_system
127
107
  @privacy = privacy
128
108
  @finalizer = finalizer
129
109
  @cast = cast
130
- @read_only = read_only
110
+ @mutable = mutable
131
111
  @as = as
132
- @dynamic_options = dynamic_options
133
112
  end
134
113
 
135
- # @return [Boolean]
136
- #
137
- # @api private
138
- # @since 0.1.0
139
- def has_default?
140
- dynamic_options.key?(:default)
141
- end
142
-
143
- # @return [Any]
144
- #
145
- # @raise [SmartCore::Initializer::NoDefaultValueError]
114
+ # @param value [Any]
115
+ # @return [void]
146
116
  #
147
117
  # @api private
148
- # @since 0.1.0
149
- def default
150
- default_value = dynamic_options.fetch(:default) do
151
- raise(SmartCore::Initializer::NoDefaultValueError, <<~ERROR_MESSAGE)
152
- Attribute #{name} has no default value
153
- ERROR_MESSAGE
154
- end
155
-
156
- default_value.is_a?(Proc) ? default_value.call : default_value
118
+ # @since 0.8.0
119
+ def validate!(value)
120
+ type.validate!(value)
121
+ rescue => error # TODO: move to typesystem interop
122
+ raise(
123
+ SmartCore::Initializer::IncorrectTypeError,
124
+ "Validation of attribute `#{name}` failed:" \
125
+ "(expected: #{type.identifier}, got: #{value.class}) \"#{error.message}\""
126
+ )
157
127
  end
158
128
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Initializer::Attribute::Value
4
+ # @api private
5
+ # @since 0.8.0
6
+ class Option < Base
7
+ # @return [Object]
8
+ #
9
+ # @api private
10
+ # @since 0.8.0
11
+ UNDEFINED_DEFAULT = ::Object.new.tap(&:freeze)
12
+
13
+ # @return [Boolean]
14
+ #
15
+ # @api private
16
+ # @since 0.8.0
17
+ DEFAULT_OPTIONAL = false
18
+
19
+ # @return [Boolean]
20
+ #
21
+ # @api private
22
+ # @since 0.8.0
23
+ attr_reader :optional
24
+ alias_method :optional?, :optional
25
+
26
+ # @param name [Symbol]
27
+ # @param type [SmartCore::Initializer::TypeSystem::Interop]
28
+ # @param type_system [Class<SmartCore::Initializer::TypeSystem::Interop>]
29
+ # @param privacy [Symbol]
30
+ # @param finalizer [SmartCore::Initializer::Attribute::AnonymousBlock/InstanceMethod]
31
+ # @param cast [Boolean]
32
+ # @param mutable [Boolean]
33
+ # @param as [NilClass, Symbol, String]
34
+ # @param default [Proc, Any]
35
+ # @param optional [Boolean]
36
+ # @return [void]
37
+ #
38
+ # @api private
39
+ # @since 0.8.0
40
+ def initialize(
41
+ name,
42
+ type,
43
+ type_system,
44
+ privacy,
45
+ finalizer,
46
+ cast,
47
+ mutable,
48
+ as,
49
+ default,
50
+ optional
51
+ )
52
+ super(name, type, type_system, privacy, finalizer, cast, mutable, as)
53
+ @default = default
54
+ @optional = optional
55
+ end
56
+
57
+ # @return [Boolean]
58
+ #
59
+ # @api private
60
+ # @since 0.8.0
61
+ def has_default?
62
+ !@default.equal?(UNDEFINED_DEFAULT)
63
+ end
64
+
65
+ # @return [Any]
66
+ #
67
+ # @raise [SmartCore::Initializer::NoDefaultValueError]
68
+ #
69
+ # @api private
70
+ # @since 0.8.0
71
+ def default
72
+ raise(
73
+ SmartCore::Initializer::NoDefaultValueError,
74
+ "Attribute #{name} has no default value"
75
+ ) if @default.equal?(UNDEFINED_DEFAULT)
76
+
77
+ @default.is_a?(Proc) ? @default.call : @default.dup
78
+ end
79
+
80
+ # @return [SmartCore::Initializer::Attribute::Value::Option]
81
+ #
82
+ # @api private
83
+ # @since 0.8.0
84
+ def dup
85
+ default = @default.equal?(UNDEFINED_DEFAULT) ? @default : @default.dup
86
+
87
+ self.class.new(
88
+ name.dup,
89
+ type,
90
+ type_system,
91
+ privacy,
92
+ finalizer.dup,
93
+ cast,
94
+ mutable,
95
+ as,
96
+ default,
97
+ optional
98
+ )
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Initializer::Attribute::Value
4
+ # @api private
5
+ # @since 0.8.0
6
+ class Param < Base
7
+ # @return [SmartCore::Initializer::Attribute::Value::Param]
8
+ #
9
+ # @api private
10
+ # @since 0.8.0
11
+ def dup
12
+ self.class.new(
13
+ name.dup,
14
+ type,
15
+ type_system,
16
+ privacy,
17
+ finalizer.dup,
18
+ cast,
19
+ mutable,
20
+ as
21
+ )
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.8.0
5
+ module SmartCore::Initializer::Attribute::Value
6
+ require_relative 'value/base'
7
+ require_relative 'value/param'
8
+ require_relative 'value/option'
9
+ end
@@ -2,132 +2,10 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
- class SmartCore::Initializer::Attribute
6
- require_relative 'attribute/parameters'
5
+ # @version 0.8.0
6
+ module SmartCore::Initializer::Attribute
7
+ require_relative 'attribute/value'
7
8
  require_relative 'attribute/list'
8
9
  require_relative 'attribute/finalizer'
9
10
  require_relative 'attribute/factory'
10
-
11
- # @since 0.1.0
12
- extend ::Forwardable
13
-
14
- # @return [Symbol]
15
- #
16
- # @pai private
17
- # @since 0.1.0
18
- def_delegator :parameters, :name
19
-
20
- # @return [SmartCore::Initializer::TypeSystem::Interop]
21
- #
22
- # @pai private
23
- # @since 0.1.0
24
- def_delegator :parameters, :type
25
-
26
- # @return [Class<SmartCore::Initializer::TypeSystem::Interop>]
27
- #
28
- # @api private
29
- # @since 0.1.0
30
- def_delegator :parameters, :type_system
31
-
32
- # @return [Symbol]
33
- #
34
- # @pai private
35
- # @since 0.1.0
36
- def_delegator :parameters, :privacy
37
-
38
- # @return [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
39
- #
40
- # @pai private
41
- # @since 0.1.0
42
- def_delegator :parameters, :finalizer
43
-
44
- # @return [Boolean]
45
- #
46
- # @pai private
47
- # @since 0.1.0
48
- def_delegators :parameters, :cast, :cast?
49
-
50
- # @return [Any]
51
- #
52
- # @api private
53
- # @since 0.1.0
54
- def_delegator :parameters, :default
55
-
56
- # @return [Boolean]
57
- #
58
- # @api private
59
- # @since 0.1.0
60
- def_delegator :parameters, :has_default?
61
-
62
- # @return [Boolean]
63
- #
64
- # @api private
65
- # @since 0.4.0
66
- def_delegator :parameters, :read_only
67
-
68
- # @return [String, Symbol, NilClass]
69
- #
70
- # @api private
71
- # @since 0.4.0
72
- def_delegator :parameters, :as
73
-
74
- # @param name [Symbol]
75
- # @param type [SmartCore::Initializer::TypeSystem::Interop]
76
- # @param type_system [Class<SmartCore::Initializer::TypeSystem::Interop>]
77
- # @param privacy [Symbol]
78
- # @param finalizer [SmartCore::Initializer::Attribute::Finalizer::AnonymousBlock/InstanceMethod]
79
- # @param cast [Boolean]
80
- # @param read_only [Boolean]
81
- # @param as [String, Symbol, NilClass]
82
- # @param dynamic_options [Hash<Symbol,Any>]
83
- # @return [void]
84
- #
85
- # @api private
86
- # @since 0.1.0
87
- def initialize(name, type, type_system, privacy, finalizer, cast, read_only, as, dynamic_options)
88
- @parameters = SmartCore::Initializer::Attribute::Parameters.new(
89
- name, type, type_system, privacy, finalizer, cast, read_only, as, dynamic_options
90
- )
91
- end
92
-
93
- # @param value [Any]
94
- # @return [void]
95
- #
96
- # @api private
97
- # @since 0.5.1
98
- def validate!(value)
99
- type.validate!(value)
100
- rescue => error
101
- raise SmartCore::Initializer::IncorrectTypeError,
102
- "Validation of attribute '#{name}' (#{type.identifier}, got #{value.class}) failed: " \
103
- "#{error.message}"
104
- end
105
-
106
- # @return [SmartCore::Initializer::Attribute]
107
- #
108
- # @api private
109
- # @since 0.1.0
110
- # rubocop:disable Metrics/AbcSize
111
- def dup
112
- self.class.new(
113
- parameters.name.dup,
114
- parameters.type,
115
- parameters.type_system,
116
- parameters.privacy,
117
- parameters.finalizer.dup,
118
- parameters.cast,
119
- parameters.read_only,
120
- parameters.as,
121
- parameters.dynamic_options.dup
122
- )
123
- end
124
- # rubocop:enable Metrics/AbcSize
125
-
126
- private
127
-
128
- # @return [SmartCore::Initializer::Attribute::Parameters]
129
- #
130
- # @api private
131
- # @since 0.1.0
132
- attr_reader :parameters
133
11
  end
@@ -25,14 +25,18 @@ module SmartCore::Initializer::Configuration
25
25
 
26
26
  # @since 0.1.0
27
27
  configuration do
28
+ # @since 0.?.0
28
29
  setting :default_type_system, :smart_types
29
30
  validate :default_type_system do |value|
30
31
  SmartCore::Initializer::TypeSystem.resolve(value) rescue false
31
32
  end
32
33
 
34
+ # @since 0.?.0
33
35
  setting :strict_options, true
34
- validate :strict_options do |value|
35
- !!value == value # check if it's a boolean value
36
- end
36
+ validate :strict_options, :boolean
37
+
38
+ # @since 0.8.0
39
+ setting :auto_cast, false
40
+ validate :auto_cast, :boolean
37
41
  end
38
42
  end