cuprum-collections 0.1.0 → 0.3.0.rc.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 +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +321 -15
- data/lib/cuprum/collections/basic/collection.rb +13 -0
- data/lib/cuprum/collections/basic/commands/destroy_one.rb +4 -3
- data/lib/cuprum/collections/basic/commands/find_many.rb +1 -1
- data/lib/cuprum/collections/basic/commands/insert_one.rb +4 -3
- data/lib/cuprum/collections/basic/commands/update_one.rb +4 -3
- data/lib/cuprum/collections/basic/query.rb +3 -3
- data/lib/cuprum/collections/basic/repository.rb +67 -0
- data/lib/cuprum/collections/commands/abstract_find_many.rb +33 -32
- data/lib/cuprum/collections/commands/abstract_find_one.rb +4 -3
- data/lib/cuprum/collections/commands/create.rb +60 -0
- data/lib/cuprum/collections/commands/find_one_matching.rb +134 -0
- data/lib/cuprum/collections/commands/update.rb +74 -0
- data/lib/cuprum/collections/commands/upsert.rb +162 -0
- data/lib/cuprum/collections/commands.rb +7 -2
- data/lib/cuprum/collections/errors/abstract_find_error.rb +210 -0
- data/lib/cuprum/collections/errors/already_exists.rb +4 -72
- data/lib/cuprum/collections/errors/extra_attributes.rb +8 -18
- data/lib/cuprum/collections/errors/failed_validation.rb +5 -18
- data/lib/cuprum/collections/errors/invalid_parameters.rb +7 -15
- data/lib/cuprum/collections/errors/invalid_query.rb +5 -15
- data/lib/cuprum/collections/errors/missing_default_contract.rb +5 -17
- data/lib/cuprum/collections/errors/not_found.rb +4 -67
- data/lib/cuprum/collections/errors/not_unique.rb +18 -0
- data/lib/cuprum/collections/errors/unknown_operator.rb +7 -17
- data/lib/cuprum/collections/errors.rb +13 -1
- data/lib/cuprum/collections/queries/ordering.rb +4 -2
- data/lib/cuprum/collections/repository.rb +105 -0
- data/lib/cuprum/collections/rspec/assign_one_command_contract.rb +2 -2
- data/lib/cuprum/collections/rspec/build_one_command_contract.rb +1 -1
- data/lib/cuprum/collections/rspec/collection_contract.rb +140 -103
- data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +8 -6
- data/lib/cuprum/collections/rspec/find_many_command_contract.rb +114 -34
- data/lib/cuprum/collections/rspec/find_one_command_contract.rb +12 -9
- data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +4 -3
- data/lib/cuprum/collections/rspec/query_contract.rb +3 -3
- data/lib/cuprum/collections/rspec/querying_contract.rb +2 -2
- data/lib/cuprum/collections/rspec/repository_contract.rb +235 -0
- data/lib/cuprum/collections/rspec/update_one_command_contract.rb +4 -3
- data/lib/cuprum/collections/version.rb +3 -3
- data/lib/cuprum/collections.rb +1 -0
- metadata +25 -91
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/errors'
|
4
|
+
|
5
|
+
module Cuprum::Collections::Errors
|
6
|
+
# Abstract base class for failed query errors.
|
7
|
+
class AbstractFindError < Cuprum::Error # rubocop:disable Metrics/ClassLength
|
8
|
+
PERMITTED_KEYWORDS = %i[
|
9
|
+
attribute_name
|
10
|
+
attribute_value
|
11
|
+
attributes
|
12
|
+
primary_key
|
13
|
+
query
|
14
|
+
].freeze
|
15
|
+
private_constant :PERMITTED_KEYWORDS
|
16
|
+
|
17
|
+
# @overload initialize(attribute_name:, attribute_value:, collection_name:, primary_key: false) # rubocop:disable Layout/LineLength
|
18
|
+
# @param attribute_name [String] The name of the queried attribute.
|
19
|
+
# @param attribute_value [Object] The value of the queried attribute.
|
20
|
+
# @param collection_name [String] The name of the collection.
|
21
|
+
# @param primary_key [true, false] Indicates that the queried attribute is
|
22
|
+
# the primary key for the collection.
|
23
|
+
#
|
24
|
+
# @overload initialize(attributes:, collection_name:)
|
25
|
+
# @param attributes [Hash<String=>Object>] The queried attributes.
|
26
|
+
# @param collection_name [String] The name of the collection.
|
27
|
+
#
|
28
|
+
# @overload initialize(query:, collection_name:)
|
29
|
+
# @param collection_name [String] The name of the collection.
|
30
|
+
# @param query [Cuprum::Collections::Query] The performed query.
|
31
|
+
def initialize(collection_name:, **options) # rubocop:disable Metrics/MethodLength
|
32
|
+
@collection_name = collection_name
|
33
|
+
@primary_key = false
|
34
|
+
|
35
|
+
resolve_options(**options)
|
36
|
+
|
37
|
+
super(
|
38
|
+
attribute_name: attribute_name,
|
39
|
+
attribute_value: attribute_value,
|
40
|
+
attributes: attributes,
|
41
|
+
collection_name: collection_name,
|
42
|
+
message: generate_message,
|
43
|
+
query: query&.criteria
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [String] the name of the queried attribute, if any.
|
48
|
+
attr_reader :attribute_name
|
49
|
+
|
50
|
+
# @return [Object] the value of the queried attribute, if any.
|
51
|
+
attr_reader :attribute_value
|
52
|
+
|
53
|
+
# @return [Hash<String=>Object>] The queried attributes.
|
54
|
+
attr_reader :attributes
|
55
|
+
|
56
|
+
# @return [String] the name of the collection.
|
57
|
+
attr_reader :collection_name
|
58
|
+
|
59
|
+
# @return [Cuprum::Collections::Query] the performed query, if any.
|
60
|
+
attr_reader :query
|
61
|
+
|
62
|
+
# @return [Array<Array>] the details of the query, in query criteria format.
|
63
|
+
def details
|
64
|
+
if attribute_name
|
65
|
+
[[attribute_name, :equal, attribute_value]]
|
66
|
+
elsif attributes
|
67
|
+
attributes
|
68
|
+
.map { |attr_name, attr_value| [attr_name, :equal, attr_value] }
|
69
|
+
elsif query
|
70
|
+
query.criteria
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [true, false] indicates that the queried attribute is the primary
|
75
|
+
# key for the collection.
|
76
|
+
def primary_key?
|
77
|
+
@primary_key
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def as_json_data
|
83
|
+
{
|
84
|
+
'collection_name' => collection_name,
|
85
|
+
'details' => details
|
86
|
+
}.merge(find_data)
|
87
|
+
end
|
88
|
+
|
89
|
+
def entity_name
|
90
|
+
titleize(tools.str.singularize(collection_name))
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_data # rubocop:disable Metrics/MethodLength
|
94
|
+
if attribute_name
|
95
|
+
{
|
96
|
+
'attribute_name' => attribute_name,
|
97
|
+
'attribute_value' => attribute_value,
|
98
|
+
'primary_key' => primary_key?
|
99
|
+
}
|
100
|
+
elsif attributes
|
101
|
+
hsh = tools.hash_tools.convert_keys_to_strings(attributes)
|
102
|
+
|
103
|
+
{ 'attributes' => hsh }
|
104
|
+
else
|
105
|
+
{}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def generate_message
|
110
|
+
core_message = "#{entity_name} #{message_fragment}"
|
111
|
+
|
112
|
+
if attribute_name
|
113
|
+
"#{core_message} with #{attribute_name.inspect} " \
|
114
|
+
"#{attribute_value.inspect}" \
|
115
|
+
"#{primary_key? ? ' (primary key)' : ''}"
|
116
|
+
elsif attributes
|
117
|
+
"#{core_message} with attributes #{attributes.inspect}"
|
118
|
+
elsif query
|
119
|
+
"#{core_message} matching the query"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def message_fragment
|
124
|
+
'query failed'
|
125
|
+
end
|
126
|
+
|
127
|
+
def resolve_attribute_options(**options)
|
128
|
+
options = options.dup
|
129
|
+
@attribute_name = options.delete(:attribute_name)
|
130
|
+
@attribute_value = options.delete(:attribute_value)
|
131
|
+
@primary_key = options.delete(:primary_key) || false
|
132
|
+
|
133
|
+
validate_keywords(extra_keywords: options.keys)
|
134
|
+
end
|
135
|
+
|
136
|
+
def resolve_attributes_options(**options)
|
137
|
+
options = options.dup
|
138
|
+
@attributes = options.delete(:attributes)
|
139
|
+
|
140
|
+
validate_keywords(extra_keywords: options.keys)
|
141
|
+
end
|
142
|
+
|
143
|
+
def resolve_query_options(**options)
|
144
|
+
options = options.dup
|
145
|
+
@query = options.delete(:query)
|
146
|
+
|
147
|
+
validate_keywords(extra_keywords: options.keys)
|
148
|
+
end
|
149
|
+
|
150
|
+
def resolve_options(**options) # rubocop:disable Metrics/MethodLength
|
151
|
+
if options[:primary_key_name] && options[:primary_key_values]
|
152
|
+
resolve_primary_key_options(**options)
|
153
|
+
elsif options[:attribute_name] && options.key?(:attribute_value)
|
154
|
+
resolve_attribute_options(**options)
|
155
|
+
elsif options[:attributes]
|
156
|
+
resolve_attributes_options(**options)
|
157
|
+
elsif options[:query]
|
158
|
+
resolve_query_options(**options)
|
159
|
+
else
|
160
|
+
raise ArgumentError,
|
161
|
+
'missing keywords :attribute_name, :attribute_value or :attributes ' \
|
162
|
+
'or :query'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def resolve_primary_key_options(**options) # rubocop:disable Metrics/MethodLength
|
167
|
+
values = Array(options[:primary_key_values])
|
168
|
+
|
169
|
+
unless values.size == 1
|
170
|
+
raise ArgumentError,
|
171
|
+
'deprecated mode does not support empty or multiple attribute values'
|
172
|
+
end
|
173
|
+
|
174
|
+
SleepingKingStudios::Tools::CoreTools
|
175
|
+
.instance
|
176
|
+
.deprecate(
|
177
|
+
'NotFound.new(primary_key_name:, primary_key_values:)',
|
178
|
+
message: 'use NotFound.new(attribute_name:, attribute_value:)'
|
179
|
+
)
|
180
|
+
|
181
|
+
@attribute_name = options[:primary_key_name]
|
182
|
+
@attribute_value = values.first
|
183
|
+
@primary_key = true
|
184
|
+
end
|
185
|
+
|
186
|
+
def titleize(string)
|
187
|
+
tools.str.underscore(string).split('_').map(&:capitalize).join(' ')
|
188
|
+
end
|
189
|
+
|
190
|
+
def tools
|
191
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
192
|
+
end
|
193
|
+
|
194
|
+
def validate_keywords(extra_keywords:) # rubocop:disable Metrics/MethodLength
|
195
|
+
return if extra_keywords.empty?
|
196
|
+
|
197
|
+
ambiguous_keywords = extra_keywords & PERMITTED_KEYWORDS
|
198
|
+
|
199
|
+
if ambiguous_keywords.empty?
|
200
|
+
raise ArgumentError,
|
201
|
+
"unknown keyword#{extra_keywords.size == 1 ? '' : 's'} " \
|
202
|
+
"#{extra_keywords.map(&:inspect).join(', ')}"
|
203
|
+
else
|
204
|
+
raise ArgumentError,
|
205
|
+
"ambiguous keyword#{extra_keywords.size == 1 ? '' : 's'} " \
|
206
|
+
"#{ambiguous_keywords.map(&:inspect).join(', ')}"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -1,86 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'cuprum/error'
|
4
|
-
|
5
3
|
require 'cuprum/collections/errors'
|
4
|
+
require 'cuprum/collections/errors/abstract_find_error'
|
6
5
|
|
7
6
|
module Cuprum::Collections::Errors
|
8
7
|
# Returned when an insert command is called with an existing record.
|
9
|
-
class AlreadyExists < Cuprum::
|
8
|
+
class AlreadyExists < Cuprum::Collections::Errors::AbstractFindError
|
10
9
|
# Short string used to identify the type of error.
|
11
10
|
TYPE = 'cuprum.collections.errors.already_exists'
|
12
11
|
|
13
|
-
# @param collection_name [String, Symbol] The name of the collection.
|
14
|
-
# @param primary_key_name [String, Symbol] The name of the primary key
|
15
|
-
# attribute.
|
16
|
-
# @param primary_key_values [Object, Array] The expected values of the
|
17
|
-
# primary key attribute.
|
18
|
-
def initialize(collection_name:, primary_key_name:, primary_key_values:)
|
19
|
-
@collection_name = collection_name
|
20
|
-
@primary_key_name = primary_key_name
|
21
|
-
@primary_key_values = Array(primary_key_values)
|
22
|
-
|
23
|
-
super(
|
24
|
-
collection_name: collection_name,
|
25
|
-
message: default_message,
|
26
|
-
primary_key_name: primary_key_name,
|
27
|
-
primary_key_values: primary_key_values
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return [String, Symbol] the name of the collection.
|
32
|
-
attr_reader :collection_name
|
33
|
-
|
34
|
-
# @return [String, Symbol] the name of the primary key attribute.
|
35
|
-
attr_reader :primary_key_name
|
36
|
-
|
37
|
-
# @return [Array] The expected values of the primary key attribute.
|
38
|
-
attr_reader :primary_key_values
|
39
|
-
|
40
|
-
# @return [Hash] a serializable hash representation of the error.
|
41
|
-
def as_json
|
42
|
-
{
|
43
|
-
'data' => {
|
44
|
-
'collection_name' => collection_name,
|
45
|
-
'primary_key_name' => primary_key_name,
|
46
|
-
'primary_key_values' => primary_key_values
|
47
|
-
},
|
48
|
-
'message' => message,
|
49
|
-
'type' => type
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
# @return [String] short string used to identify the type of error.
|
54
|
-
def type
|
55
|
-
TYPE
|
56
|
-
end
|
57
|
-
|
58
12
|
private
|
59
13
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
"#{entity_name} already exist#{singular? ? 's' : ''} with" \
|
64
|
-
" #{primary_key_name} #{primary_keys}"
|
65
|
-
end
|
66
|
-
|
67
|
-
def entity_name
|
68
|
-
entity_name = collection_name
|
69
|
-
entity_name = tools.str.singularize(entity_name) if singular?
|
70
|
-
|
71
|
-
titleize(entity_name)
|
72
|
-
end
|
73
|
-
|
74
|
-
def singular?
|
75
|
-
primary_key_values.size == 1
|
76
|
-
end
|
77
|
-
|
78
|
-
def titleize(string)
|
79
|
-
tools.str.underscore(string).split('_').map(&:capitalize).join(' ')
|
80
|
-
end
|
81
|
-
|
82
|
-
def tools
|
83
|
-
SleepingKingStudios::Tools::Toolbelt.instance
|
14
|
+
def message_fragment
|
15
|
+
'already exists'
|
84
16
|
end
|
85
17
|
end
|
86
18
|
end
|
@@ -38,29 +38,19 @@ module Cuprum::Collections::Errors
|
|
38
38
|
# @return [Array<String>] The names of valid attributes for the entity.
|
39
39
|
attr_reader :valid_attributes
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
private
|
42
|
+
|
43
|
+
def as_json_data
|
43
44
|
{
|
44
|
-
'
|
45
|
-
|
46
|
-
|
47
|
-
'valid_attributes' => valid_attributes
|
48
|
-
},
|
49
|
-
'message' => message,
|
50
|
-
'type' => type
|
45
|
+
'entity_class' => entity_class.name,
|
46
|
+
'extra_attributes' => extra_attributes,
|
47
|
+
'valid_attributes' => valid_attributes
|
51
48
|
}
|
52
49
|
end
|
53
50
|
|
54
|
-
# @return [String] short string used to identify the type of error.
|
55
|
-
def type
|
56
|
-
TYPE
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
51
|
def default_message
|
62
|
-
"invalid attributes for #{entity_class.name}:" \
|
63
|
-
"
|
52
|
+
"invalid attributes for #{entity_class.name}: " \
|
53
|
+
"#{extra_attributes.join(', ')}"
|
64
54
|
end
|
65
55
|
end
|
66
56
|
end
|
@@ -7,9 +7,6 @@ require 'cuprum/collections/errors'
|
|
7
7
|
module Cuprum::Collections::Errors
|
8
8
|
# Error returned when a collection item fails validation.
|
9
9
|
class FailedValidation < Cuprum::Error
|
10
|
-
COMPARABLE_PROPERTIES = %i[entity_class errors message].freeze
|
11
|
-
private_constant :COMPARABLE_PROPERTIES
|
12
|
-
|
13
10
|
# Short string used to identify the type of error.
|
14
11
|
TYPE = 'cuprum.collections.errors.failed_validation'
|
15
12
|
|
@@ -33,25 +30,15 @@ module Cuprum::Collections::Errors
|
|
33
30
|
# @return [Stannum::Errors] The errors generated when validating the entity.
|
34
31
|
attr_reader :errors
|
35
32
|
|
36
|
-
|
37
|
-
|
33
|
+
private
|
34
|
+
|
35
|
+
def as_json_data
|
38
36
|
{
|
39
|
-
'
|
40
|
-
|
41
|
-
'errors' => format_errors
|
42
|
-
},
|
43
|
-
'message' => message,
|
44
|
-
'type' => type
|
37
|
+
'entity_class' => entity_class.name,
|
38
|
+
'errors' => format_errors
|
45
39
|
}
|
46
40
|
end
|
47
41
|
|
48
|
-
# @return [String] short string used to identify the type of error.
|
49
|
-
def type
|
50
|
-
TYPE
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
42
|
def default_message
|
56
43
|
"#{entity_class.name} failed validation"
|
57
44
|
end
|
@@ -24,27 +24,19 @@ module Cuprum::Collections::Errors
|
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
27
|
-
# @return [Hash] a serializable hash representation of the error.
|
28
|
-
def as_json
|
29
|
-
{
|
30
|
-
'data' => {
|
31
|
-
'command_class' => command.class.name,
|
32
|
-
'errors' => errors.to_a
|
33
|
-
},
|
34
|
-
'message' => message,
|
35
|
-
'type' => type
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
27
|
# @return [Cuprum::Command] the called command.
|
40
28
|
attr_reader :command
|
41
29
|
|
42
30
|
# @return [Stannum::Errors] the errors returned by the parameters contract.
|
43
31
|
attr_reader :errors
|
44
32
|
|
45
|
-
|
46
|
-
|
47
|
-
|
33
|
+
private
|
34
|
+
|
35
|
+
def as_json_data
|
36
|
+
{
|
37
|
+
'command_class' => command.class.name,
|
38
|
+
'errors' => errors.to_a
|
39
|
+
}
|
48
40
|
end
|
49
41
|
end
|
50
42
|
end
|
@@ -29,25 +29,15 @@ module Cuprum::Collections::Errors
|
|
29
29
|
# @return [Symbol] the strategy used to construct the query.
|
30
30
|
attr_reader :strategy
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
private
|
33
|
+
|
34
|
+
def as_json_data
|
34
35
|
{
|
35
|
-
'
|
36
|
-
|
37
|
-
'strategy' => strategy
|
38
|
-
},
|
39
|
-
'message' => message,
|
40
|
-
'type' => type
|
36
|
+
'errors' => errors.to_a,
|
37
|
+
'strategy' => strategy
|
41
38
|
}
|
42
39
|
end
|
43
40
|
|
44
|
-
# @return [String] short string used to identify the type of error.
|
45
|
-
def type
|
46
|
-
TYPE
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
41
|
def default_message
|
52
42
|
"unable to parse query with strategy #{strategy.inspect}"
|
53
43
|
end
|
@@ -23,27 +23,15 @@ module Cuprum::Collections::Errors
|
|
23
23
|
# @return [Class] the class of the assigned entity.
|
24
24
|
attr_reader :entity_class
|
25
25
|
|
26
|
-
|
27
|
-
def as_json
|
28
|
-
{
|
29
|
-
'data' => {
|
30
|
-
'entity_class' => entity_class.name
|
31
|
-
},
|
32
|
-
'message' => message,
|
33
|
-
'type' => type
|
34
|
-
}
|
35
|
-
end
|
26
|
+
private
|
36
27
|
|
37
|
-
|
38
|
-
|
39
|
-
TYPE
|
28
|
+
def as_json_data
|
29
|
+
{ 'entity_class' => entity_class.name }
|
40
30
|
end
|
41
31
|
|
42
|
-
private
|
43
|
-
|
44
32
|
def default_message
|
45
|
-
"attempted to validate a #{entity_class.name}, but
|
46
|
-
|
33
|
+
"attempted to validate a #{entity_class.name}, but " \
|
34
|
+
"#{entity_class.name} does not define a default contract"
|
47
35
|
end
|
48
36
|
end
|
49
37
|
end
|
@@ -1,81 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'cuprum/error'
|
4
|
-
require 'sleeping_king_studios/tools/toolbelt'
|
5
|
-
|
6
3
|
require 'cuprum/collections/errors'
|
4
|
+
require 'cuprum/collections/errors/abstract_find_error'
|
7
5
|
|
8
6
|
module Cuprum::Collections::Errors
|
9
7
|
# Returned when a find command does not find the requested items.
|
10
|
-
class NotFound < Cuprum::
|
8
|
+
class NotFound < Cuprum::Collections::Errors::AbstractFindError
|
11
9
|
# Short string used to identify the type of error.
|
12
10
|
TYPE = 'cuprum.collections.errors.not_found'
|
13
11
|
|
14
|
-
# @param collection_name [String, Symbol] The name of the collection.
|
15
|
-
# @param primary_key_name [String, Symbol] The name of the primary key
|
16
|
-
# attribute.
|
17
|
-
# @param primary_key_values [Object, Array] The expected values of the
|
18
|
-
# primary key attribute.
|
19
|
-
def initialize(collection_name:, primary_key_name:, primary_key_values:)
|
20
|
-
@collection_name = collection_name
|
21
|
-
@primary_key_name = primary_key_name
|
22
|
-
@primary_key_values = Array(primary_key_values)
|
23
|
-
|
24
|
-
super(message: default_message)
|
25
|
-
end
|
26
|
-
|
27
|
-
# @return [String, Symbol] the name of the collection.
|
28
|
-
attr_reader :collection_name
|
29
|
-
|
30
|
-
# @return [String, Symbol] the name of the primary key attribute.
|
31
|
-
attr_reader :primary_key_name
|
32
|
-
|
33
|
-
# @return [Array] The expected values of the primary key attribute.
|
34
|
-
attr_reader :primary_key_values
|
35
|
-
|
36
|
-
# @return [Hash] a serializable hash representation of the error.
|
37
|
-
def as_json
|
38
|
-
{
|
39
|
-
'data' => {
|
40
|
-
'collection_name' => collection_name,
|
41
|
-
'primary_key_name' => primary_key_name,
|
42
|
-
'primary_key_values' => primary_key_values
|
43
|
-
},
|
44
|
-
'message' => message,
|
45
|
-
'type' => type
|
46
|
-
}
|
47
|
-
end
|
48
|
-
|
49
|
-
# @return [String] short string used to identify the type of error.
|
50
|
-
def type
|
51
|
-
TYPE
|
52
|
-
end
|
53
|
-
|
54
12
|
private
|
55
13
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
"#{entity_name} not found with #{primary_key_name} #{primary_keys}"
|
60
|
-
end
|
61
|
-
|
62
|
-
def entity_name
|
63
|
-
entity_name = collection_name
|
64
|
-
entity_name = tools.str.singularize(entity_name) if singular?
|
65
|
-
|
66
|
-
titleize(entity_name)
|
67
|
-
end
|
68
|
-
|
69
|
-
def singular?
|
70
|
-
primary_key_values.size == 1
|
71
|
-
end
|
72
|
-
|
73
|
-
def titleize(string)
|
74
|
-
tools.str.underscore(string).split('_').map(&:capitalize).join(' ')
|
75
|
-
end
|
76
|
-
|
77
|
-
def tools
|
78
|
-
SleepingKingStudios::Tools::Toolbelt.instance
|
14
|
+
def message_fragment
|
15
|
+
'not found'
|
79
16
|
end
|
80
17
|
end
|
81
18
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/errors'
|
4
|
+
require 'cuprum/collections/errors/abstract_find_error'
|
5
|
+
|
6
|
+
module Cuprum::Collections::Errors
|
7
|
+
# Returned when a unique find command does finds multiple items.
|
8
|
+
class NotUnique < Cuprum::Collections::Errors::AbstractFindError
|
9
|
+
# Short string used to identify the type of error.
|
10
|
+
TYPE = 'cuprum.collections.errors.not_unique'
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def message_fragment
|
15
|
+
'not unique'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -22,18 +22,6 @@ module Cuprum::Collections::Errors
|
|
22
22
|
# @return [String, Symbol] the unknown operator.
|
23
23
|
attr_reader :operator
|
24
24
|
|
25
|
-
# @return [Hash] a serializable hash representation of the error.
|
26
|
-
def as_json
|
27
|
-
{
|
28
|
-
'data' => {
|
29
|
-
'corrections' => corrections,
|
30
|
-
'operator' => operator
|
31
|
-
},
|
32
|
-
'message' => message,
|
33
|
-
'type' => type
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
25
|
# @return [Array<String>] Suggested possible values for the operator.
|
38
26
|
def corrections
|
39
27
|
@corrections ||=
|
@@ -42,13 +30,15 @@ module Cuprum::Collections::Errors
|
|
42
30
|
.correct(operator)
|
43
31
|
end
|
44
32
|
|
45
|
-
# @return [String] short string used to identify the type of error.
|
46
|
-
def type
|
47
|
-
TYPE
|
48
|
-
end
|
49
|
-
|
50
33
|
private
|
51
34
|
|
35
|
+
def as_json_data
|
36
|
+
{
|
37
|
+
'corrections' => corrections,
|
38
|
+
'operator' => operator
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
52
42
|
def generate_message
|
53
43
|
message = "unknown operator #{operator.inspect}"
|
54
44
|
|
@@ -4,5 +4,17 @@ require 'cuprum/collections'
|
|
4
4
|
|
5
5
|
module Cuprum::Collections
|
6
6
|
# Namespace for errors, which represent failure states of commands.
|
7
|
-
module Errors
|
7
|
+
module Errors
|
8
|
+
autoload :AbstractFindError, 'cuprum/collections/errors/abstract_find_error'
|
9
|
+
autoload :AlreadyExists, 'cuprum/collections/errors/already_exists'
|
10
|
+
autoload :ExtraAttributes, 'cuprum/collections/errors/extra_attributes'
|
11
|
+
autoload :FailedValidation, 'cuprum/collections/errors/failed_validation'
|
12
|
+
autoload :InvalidParameters, 'cuprum/collections/errors/invalid_parameters'
|
13
|
+
autoload :InvalidQuery, 'cuprum/collections/errors/invalid_query'
|
14
|
+
autoload :MissingDefaultContract,
|
15
|
+
'cuprum/collections/errors/missing_default_contract'
|
16
|
+
autoload :NotFound, 'cuprum/collections/errors/not_found'
|
17
|
+
autoload :NotUnique, 'cuprum/collections/errors/not_unique'
|
18
|
+
autoload :UnknownOperator, 'cuprum/collections/errors/unknown_operator'
|
19
|
+
end
|
8
20
|
end
|
@@ -33,6 +33,8 @@ module Cuprum::Collections::Queries
|
|
33
33
|
# @raise InvalidOrderError if any of the hash keys are invalid attribute
|
34
34
|
# names, or any of the hash values are invalid sort directions.
|
35
35
|
def normalize(*attributes)
|
36
|
+
attributes = attributes.flatten if attributes.first.is_a?(Array)
|
37
|
+
|
36
38
|
validate_ordering!(attributes)
|
37
39
|
|
38
40
|
qualified = attributes.last.is_a?(Hash) ? attributes.pop : {}
|
@@ -66,8 +68,8 @@ module Cuprum::Collections::Queries
|
|
66
68
|
return if ordering_constraint.matches?(attributes)
|
67
69
|
|
68
70
|
raise InvalidOrderError,
|
69
|
-
'order must be a list of attribute names and/or a hash of
|
70
|
-
' names with values :asc or :desc'
|
71
|
+
'order must be a list of attribute names and/or a hash of ' \
|
72
|
+
'attribute names with values :asc or :desc'
|
71
73
|
end
|
72
74
|
end
|
73
75
|
end
|