smart_initializer 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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