cuprum-collections 0.2.0 → 0.3.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 +18 -0
- data/README.md +255 -8
- 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/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 +2 -2
- data/lib/cuprum/collections/repository.rb +23 -10
- 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 +167 -93
- data/lib/cuprum/collections/rspec/update_one_command_contract.rb +4 -3
- data/lib/cuprum/collections/version.rb +1 -1
- data/lib/cuprum/collections.rb +1 -0
- metadata +20 -89
@@ -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
|
@@ -68,8 +68,8 @@ module Cuprum::Collections::Queries
|
|
68
68
|
return if ordering_constraint.matches?(attributes)
|
69
69
|
|
70
70
|
raise InvalidOrderError,
|
71
|
-
'order must be a list of attribute names and/or a hash of
|
72
|
-
' 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'
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
@@ -16,6 +16,9 @@ module Cuprum::Collections
|
|
16
16
|
class Repository
|
17
17
|
extend Forwardable
|
18
18
|
|
19
|
+
# Error raised when trying to add an existing collection to the repository.
|
20
|
+
class DuplicateCollectionError < StandardError; end
|
21
|
+
|
19
22
|
# Error raised when trying to add an invalid collection to the repository.
|
20
23
|
class InvalidCollectionError < StandardError; end
|
21
24
|
|
@@ -35,17 +38,17 @@ module Cuprum::Collections
|
|
35
38
|
|
36
39
|
# Finds and returns the collection with the given name.
|
37
40
|
#
|
38
|
-
# @param
|
39
|
-
# return.
|
41
|
+
# @param qualified_name [String, Symbol] The qualified name of the
|
42
|
+
# collection to return.
|
40
43
|
#
|
41
44
|
# @return [Object] the requested collection.
|
42
45
|
#
|
43
46
|
# @raise [Cuprum::Collection::Repository::UndefinedCOllectionError] if the
|
44
47
|
# requested collection is not in the repository.
|
45
|
-
def [](
|
46
|
-
@collections.fetch(
|
48
|
+
def [](qualified_name)
|
49
|
+
@collections.fetch(qualified_name.to_s) do
|
47
50
|
raise UndefinedCollectionError,
|
48
|
-
"repository does not define collection #{
|
51
|
+
"repository does not define collection #{qualified_name.inspect}"
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
@@ -56,12 +59,22 @@ module Cuprum::Collections
|
|
56
59
|
#
|
57
60
|
# @param collection [#collection_name] The collection to add to the
|
58
61
|
# repository.
|
62
|
+
# @param force [true, false] If true, override an existing collection with
|
63
|
+
# the same name.
|
59
64
|
#
|
60
65
|
# @return [Cuprum::Rails::Repository] the repository.
|
61
|
-
|
66
|
+
#
|
67
|
+
# @raise [DuplicateCollectionError] if a collection with the same name
|
68
|
+
# already exists in the repository.
|
69
|
+
def add(collection, force: false)
|
62
70
|
validate_collection!(collection)
|
63
71
|
|
64
|
-
|
72
|
+
if !force && key?(collection.qualified_name.to_s)
|
73
|
+
raise DuplicateCollectionError,
|
74
|
+
"collection #{collection.qualified_name} already exists"
|
75
|
+
end
|
76
|
+
|
77
|
+
@collections[collection.qualified_name.to_s] = collection
|
65
78
|
|
66
79
|
self
|
67
80
|
end
|
@@ -69,11 +82,11 @@ module Cuprum::Collections
|
|
69
82
|
|
70
83
|
# Checks if a collection with the given name exists in the repository.
|
71
84
|
#
|
72
|
-
# @param
|
85
|
+
# @param qualified_name [String, Symbol] The name to check for.
|
73
86
|
#
|
74
87
|
# @return [true, false] true if the key exists, otherwise false.
|
75
|
-
def key?(
|
76
|
-
@collections.key?(
|
88
|
+
def key?(qualified_name)
|
89
|
+
@collections.key?(qualified_name.to_s)
|
77
90
|
end
|
78
91
|
|
79
92
|
private
|