cuprum-collections 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +59 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +25 -0
- data/LICENSE +22 -0
- data/README.md +950 -0
- data/lib/cuprum/collections/base.rb +11 -0
- data/lib/cuprum/collections/basic/collection.rb +135 -0
- data/lib/cuprum/collections/basic/command.rb +112 -0
- data/lib/cuprum/collections/basic/commands/assign_one.rb +54 -0
- data/lib/cuprum/collections/basic/commands/build_one.rb +45 -0
- data/lib/cuprum/collections/basic/commands/destroy_one.rb +48 -0
- data/lib/cuprum/collections/basic/commands/find_many.rb +65 -0
- data/lib/cuprum/collections/basic/commands/find_matching.rb +126 -0
- data/lib/cuprum/collections/basic/commands/find_one.rb +49 -0
- data/lib/cuprum/collections/basic/commands/insert_one.rb +50 -0
- data/lib/cuprum/collections/basic/commands/update_one.rb +52 -0
- data/lib/cuprum/collections/basic/commands/validate_one.rb +69 -0
- data/lib/cuprum/collections/basic/commands.rb +18 -0
- data/lib/cuprum/collections/basic/query.rb +160 -0
- data/lib/cuprum/collections/basic/query_builder.rb +69 -0
- data/lib/cuprum/collections/basic/rspec/command_contract.rb +392 -0
- data/lib/cuprum/collections/basic/rspec.rb +8 -0
- data/lib/cuprum/collections/basic.rb +22 -0
- data/lib/cuprum/collections/command.rb +26 -0
- data/lib/cuprum/collections/commands/abstract_find_many.rb +77 -0
- data/lib/cuprum/collections/commands/abstract_find_matching.rb +64 -0
- data/lib/cuprum/collections/commands/abstract_find_one.rb +44 -0
- data/lib/cuprum/collections/commands.rb +8 -0
- data/lib/cuprum/collections/constraints/attribute_name.rb +22 -0
- data/lib/cuprum/collections/constraints/order/attributes_array.rb +26 -0
- data/lib/cuprum/collections/constraints/order/attributes_hash.rb +27 -0
- data/lib/cuprum/collections/constraints/order/complex_ordering.rb +46 -0
- data/lib/cuprum/collections/constraints/order/sort_direction.rb +32 -0
- data/lib/cuprum/collections/constraints/order.rb +8 -0
- data/lib/cuprum/collections/constraints/ordering.rb +114 -0
- data/lib/cuprum/collections/constraints/query_hash.rb +25 -0
- data/lib/cuprum/collections/constraints.rb +8 -0
- data/lib/cuprum/collections/errors/already_exists.rb +86 -0
- data/lib/cuprum/collections/errors/extra_attributes.rb +66 -0
- data/lib/cuprum/collections/errors/failed_validation.rb +66 -0
- data/lib/cuprum/collections/errors/invalid_parameters.rb +50 -0
- data/lib/cuprum/collections/errors/invalid_query.rb +55 -0
- data/lib/cuprum/collections/errors/missing_default_contract.rb +49 -0
- data/lib/cuprum/collections/errors/not_found.rb +81 -0
- data/lib/cuprum/collections/errors/unknown_operator.rb +71 -0
- data/lib/cuprum/collections/errors.rb +8 -0
- data/lib/cuprum/collections/queries/ordering.rb +74 -0
- data/lib/cuprum/collections/queries/parse.rb +22 -0
- data/lib/cuprum/collections/queries/parse_block.rb +206 -0
- data/lib/cuprum/collections/queries/parse_strategy.rb +91 -0
- data/lib/cuprum/collections/queries.rb +25 -0
- data/lib/cuprum/collections/query.rb +247 -0
- data/lib/cuprum/collections/query_builder.rb +61 -0
- data/lib/cuprum/collections/rspec/assign_one_command_contract.rb +168 -0
- data/lib/cuprum/collections/rspec/build_one_command_contract.rb +93 -0
- data/lib/cuprum/collections/rspec/collection_contract.rb +153 -0
- data/lib/cuprum/collections/rspec/destroy_one_command_contract.rb +106 -0
- data/lib/cuprum/collections/rspec/find_many_command_contract.rb +327 -0
- data/lib/cuprum/collections/rspec/find_matching_command_contract.rb +194 -0
- data/lib/cuprum/collections/rspec/find_one_command_contract.rb +154 -0
- data/lib/cuprum/collections/rspec/fixtures.rb +89 -0
- data/lib/cuprum/collections/rspec/insert_one_command_contract.rb +83 -0
- data/lib/cuprum/collections/rspec/query_builder_contract.rb +92 -0
- data/lib/cuprum/collections/rspec/query_contract.rb +650 -0
- data/lib/cuprum/collections/rspec/querying_contract.rb +298 -0
- data/lib/cuprum/collections/rspec/update_one_command_contract.rb +79 -0
- data/lib/cuprum/collections/rspec/validate_one_command_contract.rb +96 -0
- data/lib/cuprum/collections/rspec.rb +8 -0
- data/lib/cuprum/collections/version.rb +59 -0
- data/lib/cuprum/collections.rb +26 -0
- metadata +219 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/command_factory'
|
4
|
+
|
5
|
+
require 'cuprum/collections/basic'
|
6
|
+
require 'cuprum/collections/basic/commands'
|
7
|
+
|
8
|
+
module Cuprum::Collections::Basic
|
9
|
+
# Wraps an in-memory array of hashes data store as a Cuprum collection.
|
10
|
+
class Collection < Cuprum::CommandFactory
|
11
|
+
# @param collection_name [String, Symbol] The name of the collection.
|
12
|
+
# @param data [Array<Hash>] The current data in the collection.
|
13
|
+
# @param default_contract [Stannum::Constraints::Base, nil] The default
|
14
|
+
# contract for validating items in the collection.
|
15
|
+
# @param member_name [String] The name of a collection entity.
|
16
|
+
# @param primary_key_name [Symbol] The name of the primary key attribute.
|
17
|
+
# Defaults to :id.
|
18
|
+
# @param primary_key_type [Class, Stannum::Constraint] The type of the
|
19
|
+
# primary key attribute. Defaults to Integer.
|
20
|
+
# @param options [Hash<Symbol>] Additional options for the command.
|
21
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
22
|
+
collection_name:,
|
23
|
+
data:,
|
24
|
+
default_contract: nil,
|
25
|
+
member_name: nil,
|
26
|
+
primary_key_name: :id,
|
27
|
+
primary_key_type: Integer,
|
28
|
+
**options
|
29
|
+
)
|
30
|
+
super()
|
31
|
+
|
32
|
+
@collection_name = collection_name.to_s
|
33
|
+
@data = data
|
34
|
+
@default_contract = default_contract
|
35
|
+
@member_name =
|
36
|
+
member_name ? member_name.to_s : tools.str.singularize(@collection_name)
|
37
|
+
@options = options
|
38
|
+
@primary_key_name = primary_key_name
|
39
|
+
@primary_key_type = primary_key_type
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String] the name of the collection.
|
43
|
+
attr_reader :collection_name
|
44
|
+
|
45
|
+
# @return [Array<Hash>] the current data in the collection.
|
46
|
+
attr_reader :data
|
47
|
+
|
48
|
+
# @return [Stannum::Constraints::Base, nil] the default contract for
|
49
|
+
# validating items in the collection.
|
50
|
+
attr_reader :default_contract
|
51
|
+
|
52
|
+
# @return [String] the name of a collection entity.
|
53
|
+
attr_reader :member_name
|
54
|
+
|
55
|
+
# @return [Hash<Symbol>] additional options for the command.
|
56
|
+
attr_reader :options
|
57
|
+
|
58
|
+
# @return [Symbol] the name of the primary key attribute.
|
59
|
+
attr_reader :primary_key_name
|
60
|
+
|
61
|
+
# @return [Class, Stannum::Constraint] the type of the primary key
|
62
|
+
# attribute.
|
63
|
+
attr_reader :primary_key_type
|
64
|
+
|
65
|
+
command_class :assign_one do
|
66
|
+
Cuprum::Collections::Basic::Commands::AssignOne
|
67
|
+
.subclass(**command_options)
|
68
|
+
end
|
69
|
+
|
70
|
+
command_class :build_one do
|
71
|
+
Cuprum::Collections::Basic::Commands::BuildOne
|
72
|
+
.subclass(**command_options)
|
73
|
+
end
|
74
|
+
|
75
|
+
command_class :destroy_one do
|
76
|
+
Cuprum::Collections::Basic::Commands::DestroyOne
|
77
|
+
.subclass(**command_options)
|
78
|
+
end
|
79
|
+
|
80
|
+
command_class :find_many do
|
81
|
+
Cuprum::Collections::Basic::Commands::FindMany
|
82
|
+
.subclass(**command_options)
|
83
|
+
end
|
84
|
+
|
85
|
+
command_class :find_matching do
|
86
|
+
Cuprum::Collections::Basic::Commands::FindMatching
|
87
|
+
.subclass(**command_options)
|
88
|
+
end
|
89
|
+
|
90
|
+
command_class :find_one do
|
91
|
+
Cuprum::Collections::Basic::Commands::FindOne
|
92
|
+
.subclass(**command_options)
|
93
|
+
end
|
94
|
+
|
95
|
+
command_class :insert_one do
|
96
|
+
Cuprum::Collections::Basic::Commands::InsertOne
|
97
|
+
.subclass(**command_options)
|
98
|
+
end
|
99
|
+
|
100
|
+
command_class :update_one do
|
101
|
+
Cuprum::Collections::Basic::Commands::UpdateOne
|
102
|
+
.subclass(**command_options)
|
103
|
+
end
|
104
|
+
|
105
|
+
command_class :validate_one do
|
106
|
+
Cuprum::Collections::Basic::Commands::ValidateOne
|
107
|
+
.subclass(**command_options)
|
108
|
+
end
|
109
|
+
|
110
|
+
# A new Query instance, used for querying against the collection data.
|
111
|
+
#
|
112
|
+
# @return [Cuprum::Collections::Basic::Query] the query.
|
113
|
+
def query
|
114
|
+
Cuprum::Collections::Basic::Query.new(data)
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def command_options
|
120
|
+
@command_options ||= {
|
121
|
+
collection_name: collection_name,
|
122
|
+
data: data,
|
123
|
+
default_contract: default_contract,
|
124
|
+
member_name: member_name,
|
125
|
+
primary_key_name: primary_key_name,
|
126
|
+
primary_key_type: primary_key_type,
|
127
|
+
**options
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def tools
|
132
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/types/array_type'
|
4
|
+
|
5
|
+
require 'cuprum/collections/basic'
|
6
|
+
|
7
|
+
module Cuprum::Collections::Basic
|
8
|
+
# Abstract base class for basic collection commands.
|
9
|
+
class Command < Cuprum::Collections::Command
|
10
|
+
# Creates a subclass with the given parameters applied to the constructor.
|
11
|
+
def self.subclass(**default_options)
|
12
|
+
Class.new(self) do
|
13
|
+
define_method(:initialize) do |**options|
|
14
|
+
super(**default_options.merge(options))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param collection_name [String, Symbol] The name of the collection.
|
20
|
+
# @param data [Array<Hash>] The current data in the collection.
|
21
|
+
# @param default_contract [Stannum::Constraints::Base, nil] The default
|
22
|
+
# contract for validating items in the collection.
|
23
|
+
# @param member_name [String] The name of a collection entity.
|
24
|
+
# @param primary_key_name [Symbol] The name of the primary key attribute.
|
25
|
+
# Defaults to :id.
|
26
|
+
# @param primary_key_type [Class, Stannum::Constraint] The type of the
|
27
|
+
# primary key attribute. Defaults to Integer.
|
28
|
+
# @param options [Hash<Symbol>] Additional options for the command.
|
29
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
30
|
+
collection_name:,
|
31
|
+
data:,
|
32
|
+
default_contract: nil,
|
33
|
+
member_name: nil,
|
34
|
+
primary_key_name: :id,
|
35
|
+
primary_key_type: Integer,
|
36
|
+
**options
|
37
|
+
)
|
38
|
+
super()
|
39
|
+
|
40
|
+
@collection_name = collection_name.to_s
|
41
|
+
@data = data
|
42
|
+
@default_contract = default_contract
|
43
|
+
@member_name =
|
44
|
+
member_name ? member_name.to_s : tools.str.singularize(@collection_name)
|
45
|
+
@options = options
|
46
|
+
@primary_key_name = primary_key_name
|
47
|
+
@primary_key_type = primary_key_type
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [String] the name of the collection.
|
51
|
+
attr_reader :collection_name
|
52
|
+
|
53
|
+
# @return [Array<Hash>] the current data in the collection.
|
54
|
+
attr_reader :data
|
55
|
+
|
56
|
+
# @return [Stannum::Constraints::Base, nil] the default contract for
|
57
|
+
# validating items in the collection.
|
58
|
+
attr_reader :default_contract
|
59
|
+
|
60
|
+
# @return [String] the name of a collection entity.
|
61
|
+
attr_reader :member_name
|
62
|
+
|
63
|
+
# @return [Hash<Symbol>] additional options for the command.
|
64
|
+
attr_reader :options
|
65
|
+
|
66
|
+
# @return [Symbol] the name of the primary key attribute.
|
67
|
+
attr_reader :primary_key_name
|
68
|
+
|
69
|
+
# @return [Class, Stannum::Constraint] the type of the primary key
|
70
|
+
# attribute.
|
71
|
+
attr_reader :primary_key_type
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def primary_key_contract
|
76
|
+
type = primary_key_type
|
77
|
+
|
78
|
+
@primary_key_contract ||= Stannum::Contracts::ParametersContract.new do
|
79
|
+
keyword :primary_key, type
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def primary_keys_contract
|
84
|
+
type = primary_key_type
|
85
|
+
|
86
|
+
@primary_keys_contract ||= Stannum::Contracts::ParametersContract.new do
|
87
|
+
keyword :primary_keys,
|
88
|
+
Stannum::Constraints::Types::ArrayType.new(item_type: type)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def tools
|
93
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
94
|
+
end
|
95
|
+
|
96
|
+
def validate_primary_key(primary_key)
|
97
|
+
match_parameters_to_contract(
|
98
|
+
contract: primary_key_contract,
|
99
|
+
keywords: { primary_key: primary_key },
|
100
|
+
method_name: :call
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate_primary_keys(primary_keys)
|
105
|
+
match_parameters_to_contract(
|
106
|
+
contract: primary_keys_contract,
|
107
|
+
keywords: { primary_keys: primary_keys },
|
108
|
+
method_name: :call
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/types/hash_with_indifferent_keys'
|
4
|
+
require 'stannum/constraints/types/hash_with_string_keys'
|
5
|
+
|
6
|
+
require 'cuprum/collections/basic/command'
|
7
|
+
require 'cuprum/collections/basic/commands'
|
8
|
+
|
9
|
+
module Cuprum::Collections::Basic::Commands
|
10
|
+
# Command for assigning attributes to a collection entity.
|
11
|
+
class AssignOne < Cuprum::Collections::Basic::Command
|
12
|
+
# @!method call(attributes:, entity:)
|
13
|
+
# Assigns the given attributes to the entity.
|
14
|
+
#
|
15
|
+
# Any attributes on the entity that are not part of the given attributes
|
16
|
+
# hash are unchanged.
|
17
|
+
#
|
18
|
+
# @param attributes [Hash] The attributes and values to update.
|
19
|
+
# @param entity [Hash] The collection entity to update.
|
20
|
+
#
|
21
|
+
# @return [Hash] a copy of the entity, merged with the given attributes.
|
22
|
+
#
|
23
|
+
# @example Assigning attributes
|
24
|
+
# entity = {
|
25
|
+
# 'title' => 'The Hobbit',
|
26
|
+
# 'author' => 'J.R.R. Tolkien',
|
27
|
+
# 'series' => nil,
|
28
|
+
# 'category' => 'Science Fiction and Fantasy'
|
29
|
+
# }
|
30
|
+
# attributes = { title: 'The Silmarillion' }
|
31
|
+
# command = AssignOne.new(collection_name: 'books', data: books)
|
32
|
+
# command.call(attributes: attributes, entity: entity)
|
33
|
+
# #=> {
|
34
|
+
# 'title' => 'The Silmarillion',
|
35
|
+
# 'author' => 'J.R.R. Tolkien',
|
36
|
+
# 'series' => nil,
|
37
|
+
# 'category' => 'Science Fiction and Fantasy'
|
38
|
+
# }
|
39
|
+
validate_parameters :call do
|
40
|
+
keyword :attributes,
|
41
|
+
Stannum::Constraints::Types::HashWithIndifferentKeys.new
|
42
|
+
keyword :entity,
|
43
|
+
Stannum::Constraints::Types::HashWithStringKeys.new
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def process(attributes:, entity:)
|
49
|
+
attributes = tools.hsh.convert_keys_to_strings(attributes)
|
50
|
+
|
51
|
+
entity.merge(attributes)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/types/hash_with_indifferent_keys'
|
4
|
+
|
5
|
+
require 'cuprum/collections/basic/command'
|
6
|
+
require 'cuprum/collections/basic/commands'
|
7
|
+
|
8
|
+
module Cuprum::Collections::Basic::Commands
|
9
|
+
# Command for generating a collection entity from an attributes hash.
|
10
|
+
class BuildOne < Cuprum::Collections::Basic::Command
|
11
|
+
# @!method call(attributes:, entity:)
|
12
|
+
# Builds a new entity with the given attributes.
|
13
|
+
#
|
14
|
+
# @param attributes [Hash] The attributes and values to assign.
|
15
|
+
#
|
16
|
+
# @return [Hash] the newly built entity.
|
17
|
+
#
|
18
|
+
# @example Building an entity
|
19
|
+
# attributes = {
|
20
|
+
# 'title' => 'The Hobbit',
|
21
|
+
# 'author' => 'J.R.R. Tolkien',
|
22
|
+
# 'series' => nil,
|
23
|
+
# 'category' => 'Science Fiction and Fantasy'
|
24
|
+
# }
|
25
|
+
# command = BuildOne.new(collection_name: 'books', data: books)
|
26
|
+
# result = command.call(attributes: attributes)
|
27
|
+
# result.value
|
28
|
+
# #=> {
|
29
|
+
# 'title' => 'The Silmarillion',
|
30
|
+
# 'author' => 'J.R.R. Tolkien',
|
31
|
+
# 'series' => nil,
|
32
|
+
# 'category' => 'Science Fiction and Fantasy'
|
33
|
+
# }
|
34
|
+
validate_parameters :call do
|
35
|
+
keyword :attributes,
|
36
|
+
Stannum::Constraints::Types::HashWithIndifferentKeys.new
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def process(attributes:)
|
42
|
+
tools.hsh.convert_keys_to_strings(attributes)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cuprum/collections/basic/command'
|
4
|
+
require 'cuprum/collections/basic/commands'
|
5
|
+
require 'cuprum/collections/errors/not_found'
|
6
|
+
|
7
|
+
module Cuprum::Collections::Basic::Commands
|
8
|
+
# Command for destroying one collection item by primary key.
|
9
|
+
class DestroyOne < Cuprum::Collections::Basic::Command
|
10
|
+
# @!method call(primary_key:)
|
11
|
+
# Finds and destroys the item with the given primary key.
|
12
|
+
#
|
13
|
+
# The command will find the entity with the given primary key and remove
|
14
|
+
# it from the collection. If the entity is not found, the command will
|
15
|
+
# fail and return a NotFound error.
|
16
|
+
#
|
17
|
+
# @param primary_key [Object] The primary key of the requested item.
|
18
|
+
#
|
19
|
+
# @return [Cuprum::Result<Hash{String, Object}>] a result with the
|
20
|
+
# destroyed item.
|
21
|
+
validate_parameters :call do
|
22
|
+
keyword :primary_key, Object
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def handle_missing_item(index:, primary_key:)
|
28
|
+
return if index
|
29
|
+
|
30
|
+
error = Cuprum::Collections::Errors::NotFound.new(
|
31
|
+
collection_name: collection_name,
|
32
|
+
primary_key_name: primary_key_name,
|
33
|
+
primary_key_values: [primary_key]
|
34
|
+
)
|
35
|
+
Cuprum::Result.new(error: error)
|
36
|
+
end
|
37
|
+
|
38
|
+
def process(primary_key:)
|
39
|
+
step { validate_primary_key(primary_key) }
|
40
|
+
|
41
|
+
index = data.index { |item| item[primary_key_name.to_s] == primary_key }
|
42
|
+
|
43
|
+
step { handle_missing_item(index: index, primary_key: primary_key) }
|
44
|
+
|
45
|
+
data.delete_at(index)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/boolean'
|
4
|
+
|
5
|
+
require 'cuprum/collections/basic/command'
|
6
|
+
require 'cuprum/collections/basic/commands'
|
7
|
+
require 'cuprum/collections/commands/abstract_find_many'
|
8
|
+
|
9
|
+
module Cuprum::Collections::Basic::Commands
|
10
|
+
# Command for finding multiple collection items by primary key.
|
11
|
+
class FindMany < Cuprum::Collections::Basic::Command
|
12
|
+
include Cuprum::Collections::Commands::AbstractFindMany
|
13
|
+
|
14
|
+
# @!method call(primary_keys:, allow_partial: false, envelope: false, scope: nil) # rubocop:disable Layout/LineLength
|
15
|
+
# Queries the collection for the items with the given primary keys.
|
16
|
+
#
|
17
|
+
# The command will find and return the entities with the given primary
|
18
|
+
# keys. If any of the items are not found, the command will fail and
|
19
|
+
# return a NotFound error. If the :allow_partial option is set, the
|
20
|
+
# command will return a partial result unless none of the requested items
|
21
|
+
# are found.
|
22
|
+
#
|
23
|
+
# When the :envelope option is true, the command wraps the items in a
|
24
|
+
# Hash, using the name of the collection as the key.
|
25
|
+
#
|
26
|
+
# @param allow_partial [Boolean] If true, passes if any of the items are
|
27
|
+
# found.
|
28
|
+
# @param envelope [Boolean] If true, wraps the result value in a Hash.
|
29
|
+
# @param primary_keys [Array] The primary keys of the requested items.
|
30
|
+
# @param scope [Cuprum::Collections::Basic::Query, nil] Optional scope for
|
31
|
+
# the query. Items must match the scope as well as the primary keys.
|
32
|
+
#
|
33
|
+
# @return [Cuprum::Result<Array<Hash{String, Object}>>] a result with the
|
34
|
+
# requested items.
|
35
|
+
validate_parameters :call do
|
36
|
+
keyword :allow_partial, Stannum::Constraints::Boolean.new, default: true
|
37
|
+
keyword :envelope, Stannum::Constraints::Boolean.new, default: true
|
38
|
+
keyword :primary_keys, Array
|
39
|
+
keyword :scope, Cuprum::Collections::Basic::Query, optional: true
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def build_query
|
45
|
+
Cuprum::Collections::Basic::Query.new(data)
|
46
|
+
end
|
47
|
+
|
48
|
+
def items_with_primary_keys(items:)
|
49
|
+
# :nocov:
|
50
|
+
items.map { |item| [item[primary_key_name.to_s], item] }.to_h
|
51
|
+
# :nocov:
|
52
|
+
end
|
53
|
+
|
54
|
+
def process(
|
55
|
+
primary_keys:,
|
56
|
+
allow_partial: false,
|
57
|
+
envelope: false,
|
58
|
+
scope: nil
|
59
|
+
)
|
60
|
+
step { validate_primary_keys(primary_keys) }
|
61
|
+
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/boolean'
|
4
|
+
|
5
|
+
require 'cuprum/collections/basic/command'
|
6
|
+
require 'cuprum/collections/basic/commands'
|
7
|
+
require 'cuprum/collections/basic/query'
|
8
|
+
require 'cuprum/collections/commands/abstract_find_matching'
|
9
|
+
require 'cuprum/collections/constraints/ordering'
|
10
|
+
|
11
|
+
module Cuprum::Collections::Basic::Commands
|
12
|
+
# Command for querying filtered, ordered data from a basic collection.
|
13
|
+
class FindMatching < Cuprum::Collections::Basic::Command
|
14
|
+
include Cuprum::Collections::Commands::AbstractFindMatching
|
15
|
+
|
16
|
+
# @!method call(envelope: false, limit: nil, offset: nil, order: nil, scope: nil, where: nil, &block) # rubocop:disable Layout/LineLength
|
17
|
+
# Queries the collection for items matching the given conditions.
|
18
|
+
#
|
19
|
+
# @param envelope [Boolean] If true, wraps the result value in a Hash.
|
20
|
+
# @param limit [Integer] The maximum number of results to return.
|
21
|
+
# @param offset [Integer] The initial ordered items to skip.
|
22
|
+
# @param order [Array<String, Symbol>, Hash<{String, Symbol => Symbol}>]
|
23
|
+
# The sort order of the returned items. Should be either an array of
|
24
|
+
# attribute names or a hash of attribute names and directions.
|
25
|
+
# @param scope [Cuprum::Collections::Basic::Query, nil] Optional scope for
|
26
|
+
# the query. Items must match the scope as well as the :where filters.
|
27
|
+
# @param where [Object] Additional filters for selecting data. The command
|
28
|
+
# will only return data matching these filters.
|
29
|
+
# @yield The given block is passed to a QueryBuilder, which converts the
|
30
|
+
# block to query criteria and generates a new query using those
|
31
|
+
# criteria.
|
32
|
+
# @yieldreturn [Hash] The filters to apply to the query. The hash keys
|
33
|
+
# should be the names of attributes or columns, and the corresponding
|
34
|
+
# values should be either the literal value for that attribute or a
|
35
|
+
# method call for a valid operation defined for the query.
|
36
|
+
#
|
37
|
+
# @example Querying all items in the collection.
|
38
|
+
# command = FindMatching.new(collection_name: 'books', data: books)
|
39
|
+
# command.call
|
40
|
+
# #=> an enumerable iterating all items in the collection
|
41
|
+
#
|
42
|
+
# @example Querying all items matching some critera:
|
43
|
+
# command.call { { author: 'Nnedi Okorafor' } }
|
44
|
+
# #=> an enumerable iterating all items in the collection whose author
|
45
|
+
# is 'Nnedi Okorafor'
|
46
|
+
#
|
47
|
+
# @example Ordering query results
|
48
|
+
# command.call(order: :title) { { author: 'Nnedi Okorafor' } }
|
49
|
+
# #=> an enumerable iterating all items in the collection whose author
|
50
|
+
# # is 'Nnedi Okorafor', sorted by :title in ascending order
|
51
|
+
#
|
52
|
+
# @example Advanced filtering
|
53
|
+
# command.call do
|
54
|
+
# {
|
55
|
+
# category: eq('Science Fiction and Fantasy'),
|
56
|
+
# author: ne('J.R.R. Tolkien')
|
57
|
+
# }
|
58
|
+
# end
|
59
|
+
# #=> an enumerable iterating all items in the collection whose category
|
60
|
+
# # is 'Science Fiction and Fantasy', and whose author is not
|
61
|
+
# # 'J.R.R. Tolkien'.
|
62
|
+
#
|
63
|
+
# @example Advanced ordering
|
64
|
+
# order = { author: :asc, genre: :desc }
|
65
|
+
# command.call(order: order) { { author: 'Nnedi Okorafor' } }
|
66
|
+
# #=> an enumerable iterating all items in the collection whose author
|
67
|
+
# # is 'Nnedi Okorafor', sorted first by :author in ascending order
|
68
|
+
# # and within the same author by genre in descending order
|
69
|
+
#
|
70
|
+
# @example Filtering, ordering, and subsets
|
71
|
+
# command.call(offset: 50, limit: 10, order: :author) do
|
72
|
+
# { category: 'Science Fiction and Fantasy' }
|
73
|
+
# end
|
74
|
+
# #=> an enumerable iterating the 51st through 60th items in the
|
75
|
+
# # collection whose category is 'Science Fiction and Fantasy', sorted
|
76
|
+
# # by :author in ascending order.
|
77
|
+
#
|
78
|
+
# @example Wrapping the result in an envelope
|
79
|
+
# command =
|
80
|
+
# FindMatching.new(
|
81
|
+
# collection_name: 'books',
|
82
|
+
# data: books
|
83
|
+
# )
|
84
|
+
# command.call(envelope: true)
|
85
|
+
# #=> {
|
86
|
+
# 'books' => [] # an array containing the matching items
|
87
|
+
# }
|
88
|
+
#
|
89
|
+
# @overload call(limit: nil, offset: nil, order: nil, &block)
|
90
|
+
# When the :envelope option is false (default), the command returns an
|
91
|
+
# Enumerator which can be iterated to return the matching items.
|
92
|
+
#
|
93
|
+
# @return [Cuprum::Result<Enumerator>] the matching items in the
|
94
|
+
# specified order as an Enumerator.
|
95
|
+
#
|
96
|
+
# @overload call(limit: nil, offset: nil, order: nil, &block)
|
97
|
+
# When the :envelope option is true, the command immediately evaluates
|
98
|
+
# the query and wraps the resulting array in a Hash, using the name of
|
99
|
+
# the collection as the key.
|
100
|
+
#
|
101
|
+
# @return [Cuprum::Result<Hash{String, Array<Hash{String, Object}>}>] a
|
102
|
+
# hash with the collection name as key and the matching items as
|
103
|
+
# value.
|
104
|
+
|
105
|
+
validate_parameters :call do
|
106
|
+
keyword :envelope,
|
107
|
+
Stannum::Constraints::Boolean.new,
|
108
|
+
default: true
|
109
|
+
keyword :limit, Integer, optional: true
|
110
|
+
keyword :offset, Integer, optional: true
|
111
|
+
keyword :order,
|
112
|
+
Cuprum::Collections::Constraints::Ordering.new,
|
113
|
+
optional: true
|
114
|
+
keyword :scope,
|
115
|
+
Cuprum::Collections::Basic::Query,
|
116
|
+
optional: true
|
117
|
+
keyword :where, Object, optional: true
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def build_query
|
123
|
+
Cuprum::Collections::Basic::Query.new(data)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/boolean'
|
4
|
+
|
5
|
+
require 'cuprum/collections/basic/command'
|
6
|
+
require 'cuprum/collections/basic/commands'
|
7
|
+
require 'cuprum/collections/commands/abstract_find_one'
|
8
|
+
|
9
|
+
module Cuprum::Collections::Basic::Commands
|
10
|
+
# Command for finding one collection item by primary key.
|
11
|
+
class FindOne < Cuprum::Collections::Basic::Command
|
12
|
+
include Cuprum::Collections::Commands::AbstractFindOne
|
13
|
+
|
14
|
+
# @!method call(primary_key:, envelope: false, scope: nil)
|
15
|
+
# Queries the collection for the item with the given primary key.
|
16
|
+
#
|
17
|
+
# The command will find and return the entity with the given primary key.
|
18
|
+
# If the entity is not found, the command will fail and return a NotFound
|
19
|
+
# error.
|
20
|
+
#
|
21
|
+
# When the :envelope option is true, the command wraps the item in a Hash,
|
22
|
+
# using the singular name of the collection as the key.
|
23
|
+
#
|
24
|
+
# @param envelope [Boolean] If true, wraps the result value in a Hash.
|
25
|
+
# @param primary_key [Object] The primary key of the requested item.
|
26
|
+
# @param scope [Cuprum::Collections::Basic::Query, nil] Optional scope for
|
27
|
+
# the query. The item must match the scope as well as the primary key.
|
28
|
+
#
|
29
|
+
# @return [Cuprum::Result<Hash{String, Object}>] a result with the
|
30
|
+
# requested item.
|
31
|
+
validate_parameters :call do
|
32
|
+
keyword :envelope, Stannum::Constraints::Boolean.new, default: true
|
33
|
+
keyword :primary_key, Object
|
34
|
+
keyword :scope, Cuprum::Collections::Basic::Query, optional: true
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def build_query
|
40
|
+
Cuprum::Collections::Basic::Query.new(data)
|
41
|
+
end
|
42
|
+
|
43
|
+
def process(primary_key:, envelope: false, scope: nil)
|
44
|
+
step { validate_primary_key(primary_key) }
|
45
|
+
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|