stannum 0.3.0 → 0.4.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/README.md +129 -1263
  4. data/config/locales/en.rb +4 -0
  5. data/lib/stannum/association.rb +293 -0
  6. data/lib/stannum/associations/many.rb +250 -0
  7. data/lib/stannum/associations/one.rb +106 -0
  8. data/lib/stannum/associations.rb +11 -0
  9. data/lib/stannum/attribute.rb +86 -8
  10. data/lib/stannum/constraints/base.rb +3 -5
  11. data/lib/stannum/constraints/enum.rb +1 -1
  12. data/lib/stannum/constraints/equality.rb +1 -1
  13. data/lib/stannum/constraints/format.rb +72 -0
  14. data/lib/stannum/constraints/hashes/extra_keys.rb +7 -12
  15. data/lib/stannum/constraints/identity.rb +1 -1
  16. data/lib/stannum/constraints/properties/base.rb +1 -1
  17. data/lib/stannum/constraints/properties/do_not_match_property.rb +11 -11
  18. data/lib/stannum/constraints/properties/match_property.rb +11 -11
  19. data/lib/stannum/constraints/properties/matching.rb +7 -7
  20. data/lib/stannum/constraints/signature.rb +2 -2
  21. data/lib/stannum/constraints/tuples/extra_items.rb +6 -6
  22. data/lib/stannum/constraints/type.rb +3 -3
  23. data/lib/stannum/constraints/types/array_type.rb +2 -2
  24. data/lib/stannum/constraints/types/hash_type.rb +4 -4
  25. data/lib/stannum/constraints/union.rb +1 -1
  26. data/lib/stannum/constraints/uuid.rb +30 -0
  27. data/lib/stannum/constraints.rb +2 -0
  28. data/lib/stannum/contract.rb +7 -7
  29. data/lib/stannum/contracts/array_contract.rb +2 -7
  30. data/lib/stannum/contracts/base.rb +15 -15
  31. data/lib/stannum/contracts/builder.rb +2 -2
  32. data/lib/stannum/contracts/hash_contract.rb +3 -9
  33. data/lib/stannum/contracts/indifferent_hash_contract.rb +2 -2
  34. data/lib/stannum/contracts/map_contract.rb +6 -10
  35. data/lib/stannum/contracts/parameters/arguments_contract.rb +1 -1
  36. data/lib/stannum/contracts/parameters/keywords_contract.rb +1 -1
  37. data/lib/stannum/contracts/parameters/signature_contract.rb +1 -1
  38. data/lib/stannum/contracts/parameters_contract.rb +4 -4
  39. data/lib/stannum/contracts/tuple_contract.rb +5 -5
  40. data/lib/stannum/entities/associations.rb +451 -0
  41. data/lib/stannum/entities/attributes.rb +116 -18
  42. data/lib/stannum/entities/constraints.rb +3 -2
  43. data/lib/stannum/entities/primary_key.rb +148 -0
  44. data/lib/stannum/entities/properties.rb +30 -8
  45. data/lib/stannum/entities.rb +5 -2
  46. data/lib/stannum/entity.rb +4 -0
  47. data/lib/stannum/errors.rb +9 -13
  48. data/lib/stannum/messages/default_strategy.rb +2 -2
  49. data/lib/stannum/parameter_validation.rb +10 -10
  50. data/lib/stannum/rspec/match_errors_matcher.rb +1 -1
  51. data/lib/stannum/rspec/validate_parameter.rb +2 -2
  52. data/lib/stannum/rspec/validate_parameter_matcher.rb +15 -13
  53. data/lib/stannum/schema.rb +62 -62
  54. data/lib/stannum/support/optional.rb +1 -1
  55. data/lib/stannum/version.rb +4 -4
  56. data/lib/stannum.rb +3 -0
  57. metadata +14 -79
@@ -2,159 +2,159 @@
2
2
 
3
3
  require 'forwardable'
4
4
 
5
- require 'stannum/attribute'
6
-
7
5
  module Stannum
8
- # Abstract class for defining attribute methods for a struct.
6
+ # Abstract class for defining property methods for an entity.
9
7
  #
10
8
  # @see Stannum::Attribute.
11
9
  class Schema < Module
12
10
  extend Forwardable
13
11
  include Enumerable
14
12
 
15
- def initialize
16
- super
13
+ # @param property_class [Class] the class representing the elements of the
14
+ # schema.
15
+ # @param property_name [String, Symbol] the name of the schema elements.
16
+ def initialize(property_class:, property_name:)
17
+ super()
18
+
19
+ tools.assertions.validate_class(property_class, as: 'property class')
20
+ tools.assertions.validate_name(property_name, as: 'property name')
17
21
 
18
- @attributes = {}
22
+ @properties = {}
23
+ @property_class = property_class
24
+ @property_name = property_name.to_s
19
25
  end
20
26
 
21
- # Retrieves the named attribute object.
27
+ # @return [Class] the class representing the elements of the schema.
28
+ attr_reader :property_class
29
+
30
+ # @return [String] the name of the schema elements.
31
+ attr_reader :property_name
32
+
33
+ # Retrieves the named property object.
22
34
  #
23
- # @param key [String, Symbol] The name of the requested attribute.
35
+ # @param key [String, Symbol] The name of the requested property.
24
36
  #
25
- # @return [Stannum::Attribute] The attribute object.
37
+ # @return [Stannum::Attribute] The property object.
26
38
  #
27
39
  # @raise ArgumentError if the key is invalid.
28
- # @raise KeyError if the attribute is not defined.
40
+ # @raise KeyError if the property is not defined.
29
41
  def [](key)
30
42
  tools.assertions.assert_name(key, as: 'key', error_class: ArgumentError)
31
43
 
32
44
  str = -key.to_s
33
45
 
34
46
  each_ancestor do |ancestor|
35
- next unless ancestor.own_attributes.key?(str)
47
+ next unless ancestor.own_properties.key?(str)
36
48
 
37
- return ancestor.own_attributes[str]
49
+ return ancestor.own_properties[str]
38
50
  end
39
51
 
40
52
  {}.fetch(str)
41
53
  end
42
54
 
43
- # rubocop:disable Metrics/MethodLength
44
-
45
55
  # @api private
46
56
  #
47
- # Defines an attribute and adds the attribute to the contract.
57
+ # Defines an property and adds the property to the contract.
48
58
  #
49
- # This method should not be called directly. Instead, define attributes via
50
- # the Struct.attribute class method.
59
+ # This method should not be called directly. Instead, define properties via
60
+ # the Struct.property class method.
51
61
  #
52
62
  # @see Stannum::Struct
53
- def define_attribute(name:, options:, type:)
54
- attribute = Stannum::Attribute.new(
55
- name: name,
56
- options: options,
57
- type: type
58
- )
59
-
60
- if @attributes.key?(attribute.name)
61
- raise ArgumentError, "attribute #{name.inspect} already exists"
63
+ def define(name:, options:, type:, definition_class: nil)
64
+ definition_class ||= property_class
65
+
66
+ property = definition_class.new(name:, options:, type:)
67
+
68
+ if @properties.key?(property.name)
69
+ message =
70
+ "#{tools.str.singularize(property_name)} #{name.inspect} " \
71
+ 'already exists'
72
+
73
+ raise ArgumentError, message
62
74
  end
63
75
 
64
- define_reader(attribute.name, attribute.reader_name)
65
- define_writer(attribute.name, attribute.writer_name, attribute.default)
76
+ definition_class::Builder.new(self).call(property)
66
77
 
67
- @attributes[attribute.name] = attribute
78
+ @properties[property.name] = property
68
79
  end
69
- # rubocop:enable Metrics/MethodLength
70
80
 
71
- # Iterates through the the attributes by name and attribute object.
81
+ # Iterates through the the properties by name and property object.
72
82
  #
73
- # @yieldparam name [String] The name of the attribute.
74
- # @yieldparam attribute [Stannum::Attribute] The attribute object.
83
+ # @yieldparam name [String] The name of the property.
84
+ # @yieldparam property [Stannum::Attribute] The property object.
75
85
  def each(&block)
76
86
  return enum_for(:each) { size } unless block_given?
77
87
 
78
88
  each_ancestor do |ancestor|
79
- ancestor.own_attributes.each(&block)
89
+ ancestor.own_properties.each(&block)
80
90
  end
81
91
  end
82
92
 
83
- # Iterates through the the attributes by name.
93
+ # Iterates through the the properties by name.
84
94
  #
85
- # @yieldparam name [String] The name of the attribute.
95
+ # @yieldparam name [String] The name of the property.
86
96
  def each_key(&block)
87
97
  return enum_for(:each_key) { size } unless block_given?
88
98
 
89
99
  each_ancestor do |ancestor|
90
- ancestor.own_attributes.each_key(&block)
100
+ ancestor.own_properties.each_key(&block)
91
101
  end
92
102
  end
93
103
 
94
- # Iterates through the the attributes by attribute object.
104
+ # Iterates through the the properties by property object.
95
105
  #
96
- # @yieldparam attribute [Stannum::Attribute] The attribute object.
106
+ # @yieldparam property [Stannum::Attribute] The property object.
97
107
  def each_value(&block)
98
108
  return enum_for(:each_value) { size } unless block_given?
99
109
 
100
110
  each_ancestor do |ancestor|
101
- ancestor.own_attributes.each_value(&block)
111
+ ancestor.own_properties.each_value(&block)
102
112
  end
103
113
  end
104
114
 
105
- # Checks if the given attribute is defined.
115
+ # Checks if the given property is defined.
106
116
  #
107
- # @param key [String, Symbol] the name of the attribute to check.
117
+ # @param key [String, Symbol] the name of the property to check.
108
118
  #
109
- # @return [Boolean] true if the attribute is defined; otherwise false.
119
+ # @return [Boolean] true if the property is defined; otherwise false.
110
120
  def key?(key)
111
121
  tools.assertions.assert_name(key, as: 'key', error_class: ArgumentError)
112
122
 
113
123
  each_ancestor.any? do |ancestor|
114
- ancestor.own_attributes.key?(key.to_s)
124
+ ancestor.own_properties.key?(key.to_s)
115
125
  end
116
126
  end
117
127
  alias has_key? key?
118
128
 
119
- # Returns the defined attribute keys.
129
+ # Returns the defined property keys.
120
130
  #
121
- # @return [Array<String>] the attribute keys.
131
+ # @return [Array<String>] the property keys.
122
132
  def keys
123
133
  each_key.to_a
124
134
  end
125
135
 
126
136
  # @private
127
- def own_attributes
128
- @attributes
137
+ def own_properties
138
+ @properties
129
139
  end
130
140
 
131
- # @return [Integer] the number of defined attributes.
141
+ # @return [Integer] the number of defined properties.
132
142
  def size
133
143
  each_ancestor.reduce(0) do |memo, ancestor|
134
- memo + ancestor.own_attributes.size
144
+ memo + ancestor.own_properties.size
135
145
  end
136
146
  end
137
147
  alias count size
138
148
 
139
- # Returns the defined attribute value.
149
+ # Returns the defined property value.
140
150
  #
141
- # @return [Array<Stannum::Attribute>] the attribute values.
151
+ # @return [Array<Stannum::Attribute>] the property values.
142
152
  def values
143
153
  each_value.to_a
144
154
  end
145
155
 
146
156
  private
147
157
 
148
- def define_reader(attr_name, reader_name)
149
- define_method(reader_name) { @attributes[attr_name] }
150
- end
151
-
152
- def define_writer(attr_name, writer_name, default_value)
153
- define_method(writer_name) do |value|
154
- @attributes[attr_name] = value.nil? ? default_value : value
155
- end
156
- end
157
-
158
158
  def each_ancestor
159
159
  return enum_for(:each_ancestor) unless block_given?
160
160
 
@@ -20,7 +20,7 @@ module Stannum::Support
20
20
 
21
21
  options.merge(
22
22
  required: required?(
23
- default: default,
23
+ default:,
24
24
  optional: validate_option(optional, as: :optional),
25
25
  required: validate_option(required, as: :required)
26
26
  )
@@ -10,7 +10,7 @@ module Stannum
10
10
  # Major version.
11
11
  MAJOR = 0
12
12
  # Minor version.
13
- MINOR = 3
13
+ MINOR = 4
14
14
  # Patch version.
15
15
  PATCH = 0
16
16
  # Prerelease version.
@@ -27,13 +27,13 @@ module Stannum
27
27
  #
28
28
  # @see SleepingKingStudios::Tools::SemanticVersion#to_gem_version
29
29
  def to_gem_version
30
- str = +"#{MAJOR}.#{MINOR}.#{PATCH}"
30
+ str = "#{MAJOR}.#{MINOR}.#{PATCH}"
31
31
 
32
32
  prerelease = value_of(:PRERELEASE)
33
- str << ".#{prerelease}" if prerelease
33
+ str = "#{str}.#{prerelease}" if prerelease
34
34
 
35
35
  build = value_of(:BUILD)
36
- str << ".#{build}" if build
36
+ str = "#{str}.#{build}" if build
37
37
 
38
38
  str
39
39
  end
data/lib/stannum.rb CHANGED
@@ -4,6 +4,9 @@ require 'stannum/version'
4
4
 
5
5
  # A library for specifying and validating data structures.
6
6
  module Stannum
7
+ autoload :Association, 'stannum/association'
8
+ autoload :Associations, 'stannum/associations'
9
+ autoload :Attribute, 'stannum/attribute'
7
10
  autoload :Constraint, 'stannum/constraint'
8
11
  autoload :Constraints, 'stannum/constraints'
9
12
  autoload :Contract, 'stannum/contract'
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stannum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob "Merlin" Smith
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-03-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: sleeping_king_studios-tools
@@ -16,84 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: 1.1.0
18
+ version: '1.1'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: 1.1.0
27
- - !ruby/object:Gem::Dependency
28
- name: rspec
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '3.10'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '3.10'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec-sleeping_king_studios
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.6'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.6'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.48'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.48'
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop-rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '2.19'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '2.19'
83
- - !ruby/object:Gem::Dependency
84
- name: simplecov
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '0.21'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '0.21'
25
+ version: '1.1'
97
26
  description: |-
98
27
  A focused library for specifying and validating data structures. Stannum
99
28
  provides tools to define data schemas for domain objects, method arguments,
@@ -112,6 +41,10 @@ files:
112
41
  - README.md
113
42
  - config/locales/en.rb
114
43
  - lib/stannum.rb
44
+ - lib/stannum/association.rb
45
+ - lib/stannum/associations.rb
46
+ - lib/stannum/associations/many.rb
47
+ - lib/stannum/associations/one.rb
115
48
  - lib/stannum/attribute.rb
116
49
  - lib/stannum/constraint.rb
117
50
  - lib/stannum/constraints.rb
@@ -122,6 +55,7 @@ files:
122
55
  - lib/stannum/constraints/delegator.rb
123
56
  - lib/stannum/constraints/enum.rb
124
57
  - lib/stannum/constraints/equality.rb
58
+ - lib/stannum/constraints/format.rb
125
59
  - lib/stannum/constraints/hashes.rb
126
60
  - lib/stannum/constraints/hashes/extra_keys.rb
127
61
  - lib/stannum/constraints/hashes/indifferent_extra_keys.rb
@@ -161,6 +95,7 @@ files:
161
95
  - lib/stannum/constraints/types/symbol_type.rb
162
96
  - lib/stannum/constraints/types/time_type.rb
163
97
  - lib/stannum/constraints/union.rb
98
+ - lib/stannum/constraints/uuid.rb
164
99
  - lib/stannum/contract.rb
165
100
  - lib/stannum/contracts.rb
166
101
  - lib/stannum/contracts/array_contract.rb
@@ -177,8 +112,10 @@ files:
177
112
  - lib/stannum/contracts/parameters_contract.rb
178
113
  - lib/stannum/contracts/tuple_contract.rb
179
114
  - lib/stannum/entities.rb
115
+ - lib/stannum/entities/associations.rb
180
116
  - lib/stannum/entities/attributes.rb
181
117
  - lib/stannum/entities/constraints.rb
118
+ - lib/stannum/entities/primary_key.rb
182
119
  - lib/stannum/entities/properties.rb
183
120
  - lib/stannum/entity.rb
184
121
  - lib/stannum/errors.rb
@@ -204,7 +141,6 @@ metadata:
204
141
  bug_tracker_uri: https://github.com/sleepingkingstudios/stannum/issues
205
142
  source_code_uri: https://github.com/sleepingkingstudios/stannum
206
143
  rubygems_mfa_required: 'true'
207
- post_install_message:
208
144
  rdoc_options: []
209
145
  require_paths:
210
146
  - lib
@@ -212,15 +148,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
212
148
  requirements:
213
149
  - - ">="
214
150
  - !ruby/object:Gem::Version
215
- version: '2.7'
151
+ version: '3.1'
216
152
  required_rubygems_version: !ruby/object:Gem::Requirement
217
153
  requirements:
218
154
  - - ">="
219
155
  - !ruby/object:Gem::Version
220
156
  version: '0'
221
157
  requirements: []
222
- rubygems_version: 3.4.1
223
- signing_key:
158
+ rubygems_version: 3.6.9
224
159
  specification_version: 4
225
160
  summary: A library for specifying and validating data structures.
226
161
  test_files: []