cuprum-collections 0.5.1 → 0.6.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/lib/cuprum/collections/adaptable/collection.rb +18 -0
  4. data/lib/cuprum/collections/adaptable/command.rb +22 -0
  5. data/lib/cuprum/collections/adaptable/commands/abstract_assign_one.rb +27 -0
  6. data/lib/cuprum/collections/adaptable/commands/abstract_build_one.rb +25 -0
  7. data/lib/cuprum/collections/adaptable/commands/abstract_validate_one.rb +35 -0
  8. data/lib/cuprum/collections/adaptable/commands.rb +15 -0
  9. data/lib/cuprum/collections/adaptable/query.rb +64 -0
  10. data/lib/cuprum/collections/adaptable.rb +13 -0
  11. data/lib/cuprum/collections/adapter.rb +300 -0
  12. data/lib/cuprum/collections/adapters/data_adapter.rb +82 -0
  13. data/lib/cuprum/collections/adapters/entity_adapter.rb +76 -0
  14. data/lib/cuprum/collections/adapters/hash_adapter.rb +48 -0
  15. data/lib/cuprum/collections/adapters.rb +14 -0
  16. data/lib/cuprum/collections/basic/collection.rb +2 -20
  17. data/lib/cuprum/collections/basic/commands/destroy_one.rb +1 -1
  18. data/lib/cuprum/collections/basic/commands/find_many.rb +0 -31
  19. data/lib/cuprum/collections/basic/commands/find_matching.rb +0 -94
  20. data/lib/cuprum/collections/basic/commands/find_one.rb +0 -18
  21. data/lib/cuprum/collections/basic/commands/insert_one.rb +1 -1
  22. data/lib/cuprum/collections/basic/commands/update_one.rb +1 -1
  23. data/lib/cuprum/collections/basic/scopes/criteria_scope.rb +36 -21
  24. data/lib/cuprum/collections/basic.rb +6 -5
  25. data/lib/cuprum/collections/collection.rb +6 -0
  26. data/lib/cuprum/collections/collection_command.rb +1 -1
  27. data/lib/cuprum/collections/commands/abstract_find_many.rb +40 -3
  28. data/lib/cuprum/collections/commands/abstract_find_matching.rb +102 -0
  29. data/lib/cuprum/collections/commands/abstract_find_one.rb +23 -1
  30. data/lib/cuprum/collections/commands/associations/find_many.rb +1 -3
  31. data/lib/cuprum/collections/commands/associations/require_many.rb +1 -1
  32. data/lib/cuprum/collections/commands/find_one_matching.rb +10 -10
  33. data/lib/cuprum/collections/commands/query_command.rb +6 -4
  34. data/lib/cuprum/collections/commands/upsert.rb +0 -2
  35. data/lib/cuprum/collections/constraints/order/attributes_array.rb +5 -4
  36. data/lib/cuprum/collections/constraints/order/attributes_hash.rb +5 -4
  37. data/lib/cuprum/collections/constraints/order/sort_direction.rb +2 -2
  38. data/lib/cuprum/collections/constraints/ordering.rb +11 -9
  39. data/lib/cuprum/collections/constraints/query_hash.rb +2 -2
  40. data/lib/cuprum/collections/errors/abstract_find_error.rb +101 -23
  41. data/lib/cuprum/collections/errors/extra_attributes.rb +3 -3
  42. data/lib/cuprum/collections/errors/failed_validation.rb +3 -3
  43. data/lib/cuprum/collections/errors/missing_default_contract.rb +12 -4
  44. data/lib/cuprum/collections/queries.rb +4 -0
  45. data/lib/cuprum/collections/relation.rb +0 -2
  46. data/lib/cuprum/collections/relations/parameters.rb +120 -68
  47. data/lib/cuprum/collections/repository.rb +71 -6
  48. data/lib/cuprum/collections/rspec/contracts/query_contracts.rb +23 -4
  49. data/lib/cuprum/collections/rspec/contracts/repository_contracts.rb +18 -0
  50. data/lib/cuprum/collections/rspec/contracts/scope_contracts.rb +51 -0
  51. data/lib/cuprum/collections/rspec/contracts/scopes/builder_contracts.rb +10 -0
  52. data/lib/cuprum/collections/rspec/contracts/scopes/composition_contracts.rb +8 -0
  53. data/lib/cuprum/collections/rspec/contracts/scopes/criteria_contracts.rb +18 -366
  54. data/lib/cuprum/collections/rspec/contracts/scopes/logical_contracts.rb +30 -0
  55. data/lib/cuprum/collections/rspec/contracts/scopes.rb +2 -0
  56. data/lib/cuprum/collections/rspec/contracts.rb +2 -10
  57. data/lib/cuprum/collections/rspec/deferred/adapter_examples.rb +1077 -0
  58. data/lib/cuprum/collections/rspec/deferred/collection_examples.rb +27 -7
  59. data/lib/cuprum/collections/rspec/deferred/commands/assign_one_examples.rb +4 -4
  60. data/lib/cuprum/collections/rspec/deferred/commands/build_one_examples.rb +2 -2
  61. data/lib/cuprum/collections/rspec/deferred/commands/destroy_one_examples.rb +2 -2
  62. data/lib/cuprum/collections/rspec/deferred/commands/find_many_examples.rb +5 -5
  63. data/lib/cuprum/collections/rspec/deferred/commands/find_matching_examples.rb +45 -12
  64. data/lib/cuprum/collections/rspec/deferred/commands/find_one_examples.rb +2 -2
  65. data/lib/cuprum/collections/rspec/deferred/commands/insert_one_examples.rb +1 -1
  66. data/lib/cuprum/collections/rspec/deferred/commands/update_one_examples.rb +1 -1
  67. data/lib/cuprum/collections/rspec/deferred/query_examples.rb +930 -0
  68. data/lib/cuprum/collections/rspec/deferred/relation_examples.rb +48 -17
  69. data/lib/cuprum/collections/rspec/deferred/repository_examples.rb +961 -0
  70. data/lib/cuprum/collections/rspec/deferred/scope_examples.rb +598 -0
  71. data/lib/cuprum/collections/rspec/deferred/scopes/all_examples.rb +391 -0
  72. data/lib/cuprum/collections/rspec/deferred/scopes/builder_examples.rb +857 -0
  73. data/lib/cuprum/collections/rspec/deferred/scopes/composition_examples.rb +93 -0
  74. data/lib/cuprum/collections/rspec/deferred/scopes/conjunction_examples.rb +438 -0
  75. data/lib/cuprum/collections/rspec/deferred/scopes/criteria_examples.rb +1941 -0
  76. data/lib/cuprum/collections/rspec/deferred/scopes/disjunction_examples.rb +415 -0
  77. data/lib/cuprum/collections/rspec/deferred/scopes/none_examples.rb +385 -0
  78. data/lib/cuprum/collections/rspec/deferred/scopes/parser_examples.rb +740 -0
  79. data/lib/cuprum/collections/rspec/deferred/scopes.rb +8 -0
  80. data/lib/cuprum/collections/scope.rb +2 -2
  81. data/lib/cuprum/collections/scopes/container.rb +5 -4
  82. data/lib/cuprum/collections/scopes/criteria/parser.rb +24 -48
  83. data/lib/cuprum/collections/scopes/criteria.rb +7 -6
  84. data/lib/cuprum/collections/version.rb +4 -4
  85. data/lib/cuprum/collections.rb +5 -1
  86. metadata +47 -11
  87. data/lib/cuprum/collections/rspec/contracts/association_contracts.rb +0 -2127
  88. data/lib/cuprum/collections/rspec/contracts/basic.rb +0 -11
  89. data/lib/cuprum/collections/rspec/contracts/collection_contracts.rb +0 -387
  90. data/lib/cuprum/collections/rspec/contracts/command_contracts.rb +0 -169
  91. data/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +0 -1264
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'cuprum/parameter_validation'
4
+
3
5
  require 'cuprum/collections/commands'
4
6
  require 'cuprum/collections/constraints/ordering'
5
7
  require 'cuprum/collections/errors/invalid_query'
@@ -7,6 +9,102 @@ require 'cuprum/collections/errors/invalid_query'
7
9
  module Cuprum::Collections::Commands
8
10
  # Abstract implementation of the FindMatching command.
9
11
  module AbstractFindMatching
12
+ include Cuprum::ParameterValidation
13
+
14
+ # @!method call(envelope: false, limit: nil, offset: nil, order: nil, scope: nil, where: nil, &block)
15
+ # Queries the collection for items matching the given conditions.
16
+ #
17
+ # @param envelope [Boolean] If true, wraps the result value in a Hash.
18
+ # @param limit [Integer] The maximum number of results to return.
19
+ # @param offset [Integer] The initial ordered items to skip.
20
+ # @param order [Array<String, Symbol>, Hash<{String, Symbol => Symbol}>]
21
+ # The sort order of the returned items. Should be either an array of
22
+ # attribute names or a hash of attribute names and directions.
23
+ # @param scope [Cuprum::Collections::Basic::Query, nil] Optional scope for
24
+ # the query. Items must match the scope as well as the :where filters.
25
+ # @param where [Object] Additional filters for selecting data. The command
26
+ # will only return data matching these filters.
27
+ # @yield The given block is passed to a QueryBuilder, which converts the
28
+ # block to query criteria and generates a new query using those
29
+ # criteria.
30
+ # @yieldreturn [Hash] The filters to apply to the query. The hash keys
31
+ # should be the names of attributes or columns, and the corresponding
32
+ # values should be either the literal value for that attribute or a
33
+ # method call for a valid operation defined for the query.
34
+ #
35
+ # @example Querying all items in the collection.
36
+ # command = FindMatching.new(collection_name: 'books', data: books)
37
+ # command.call
38
+ # #=> an enumerable iterating all items in the collection
39
+ #
40
+ # @example Querying all items matching some critera:
41
+ # command.call { { author: 'Nnedi Okorafor' } }
42
+ # #=> an enumerable iterating all items in the collection whose author
43
+ # is 'Nnedi Okorafor'
44
+ #
45
+ # @example Ordering query results
46
+ # command.call(order: :title) { { author: 'Nnedi Okorafor' } }
47
+ # #=> an enumerable iterating all items in the collection whose author
48
+ # # is 'Nnedi Okorafor', sorted by :title in ascending order
49
+ #
50
+ # @example Advanced filtering
51
+ # command.call do
52
+ # {
53
+ # category: eq('Science Fiction and Fantasy'),
54
+ # author: ne('J.R.R. Tolkien')
55
+ # }
56
+ # end
57
+ # #=> an enumerable iterating all items in the collection whose category
58
+ # # is 'Science Fiction and Fantasy', and whose author is not
59
+ # # 'J.R.R. Tolkien'.
60
+ #
61
+ # @example Advanced ordering
62
+ # order = { author: :asc, genre: :desc }
63
+ # command.call(order: order) { { author: 'Nnedi Okorafor' } }
64
+ # #=> an enumerable iterating all items in the collection whose author
65
+ # # is 'Nnedi Okorafor', sorted first by :author in ascending order
66
+ # # and within the same author by genre in descending order
67
+ #
68
+ # @example Filtering, ordering, and subsets
69
+ # command.call(offset: 50, limit: 10, order: :author) do
70
+ # { category: 'Science Fiction and Fantasy' }
71
+ # end
72
+ # #=> an enumerable iterating the 51st through 60th items in the
73
+ # # collection whose category is 'Science Fiction and Fantasy', sorted
74
+ # # by :author in ascending order.
75
+ #
76
+ # @example Wrapping the result in an envelope
77
+ # command =
78
+ # FindMatching.new(
79
+ # collection_name: 'books',
80
+ # data: books
81
+ # )
82
+ # command.call(envelope: true)
83
+ # #=> {
84
+ # 'books' => [] # an array containing the matching items
85
+ # }
86
+ #
87
+ # @overload call(limit: nil, offset: nil, order: nil, &block)
88
+ # When the :envelope option is false (default), the command returns an
89
+ # Enumerator which can be iterated to return the matching items.
90
+ #
91
+ # @return [Cuprum::Result<Enumerator>] the matching items in the
92
+ # specified order as an Enumerator.
93
+ #
94
+ # @overload call(limit: nil, offset: nil, order: nil, &block)
95
+ # When the :envelope option is true, the command immediately evaluates
96
+ # the query and wraps the resulting array in a Hash, using the name of
97
+ # the collection as the key.
98
+ #
99
+ # @return [Cuprum::Result<Hash{String, Array<Hash{String, Object}>}>] a
100
+ # hash with the collection name as key and the matching items as
101
+ # value.
102
+ validate :envelope, :boolean, optional: true
103
+ validate :limit, Integer, optional: true
104
+ validate :offset, Integer, optional: true
105
+ validate :order
106
+ validate :where
107
+
10
108
  private
11
109
 
12
110
  def apply_query(limit:, offset:, order:, scope:)
@@ -22,6 +120,8 @@ module Cuprum::Collections::Commands
22
120
  def build_scope(value, &)
23
121
  return Cuprum::Collections::Scope.build(&) if block_given?
24
122
 
123
+ return Cuprum::Collections::Scope.build(&value) if value.is_a?(Proc)
124
+
25
125
  return value if value.is_a?(Cuprum::Collections::Scopes::Base)
26
126
 
27
127
  Cuprum::Collections::Scope.build(value) if value
@@ -69,6 +169,8 @@ module Cuprum::Collections::Commands
69
169
  def validate_where(value, as: 'where')
70
170
  return if value.nil?
71
171
 
172
+ return if value.is_a?(Proc) && (-1..1).cover?(value.arity)
173
+
72
174
  return if value.is_a?(Cuprum::Collections::Scopes::Base)
73
175
 
74
176
  return if validate_attributes(value, as:).empty?
@@ -1,11 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'cuprum/parameter_validation'
4
+
3
5
  require 'cuprum/collections/commands'
4
6
  require 'cuprum/collections/errors/not_found'
5
7
 
6
8
  module Cuprum::Collections::Commands
7
9
  # Abstract implementation of the FindOne command.
8
10
  module AbstractFindOne
11
+ include Cuprum::ParameterValidation
12
+
13
+ # @!method call(primary_key:, envelope: false)
14
+ # Queries the collection for the item with the given primary key.
15
+ #
16
+ # The command will find and return the entity with the given primary key.
17
+ # If the entity is not found, the command will fail and return a NotFound
18
+ # error.
19
+ #
20
+ # When the :envelope option is true, the command wraps the item in a Hash,
21
+ # using the singular name of the collection as the key.
22
+ #
23
+ # @param envelope [Boolean] If true, wraps the result value in a Hash.
24
+ # @param primary_key [Object] The primary key of the requested item.
25
+ #
26
+ # @return [Cuprum::Result<Hash{String, Object}>] a result with the
27
+ # requested item.
28
+ validate :envelope, :boolean, optional: true
29
+ validate :primary_key
30
+
9
31
  private
10
32
 
11
33
  def apply_query(primary_key:)
@@ -20,7 +42,7 @@ module Cuprum::Collections::Commands
20
42
  error = Cuprum::Collections::Errors::NotFound.new(
21
43
  attribute_name: primary_key_name,
22
44
  attribute_value: primary_key,
23
- collection_name:,
45
+ name:,
24
46
  primary_key: true
25
47
  )
26
48
  Cuprum::Result.new(error:)
@@ -74,9 +74,7 @@ module Cuprum::Collections::Commands::Associations
74
74
  private
75
75
 
76
76
  def collection
77
- repository.find_or_create(
78
- qualified_name: association.qualified_name
79
- )
77
+ repository.find(qualified_name: association.qualified_name)
80
78
  end
81
79
 
82
80
  def extract_keys(association, hsh)
@@ -24,7 +24,7 @@ module Cuprum::Collections::Commands::Associations
24
24
  Cuprum::Collections::Errors::NotFound.new(
25
25
  attribute_name: association.query_key_name,
26
26
  attribute_value:,
27
- collection_name: association.name,
27
+ name: association.name,
28
28
  primary_key: association.primary_key_query?
29
29
  )
30
30
  end
@@ -91,25 +91,25 @@ module Cuprum::Collections::Commands
91
91
 
92
92
  private
93
93
 
94
- def error_params_for(attributes: nil, &block)
95
- { collection_name: collection.name }.merge(
94
+ def error_params_for(attributes: nil, &)
95
+ { name: collection.name }.merge(
96
96
  if block_given?
97
- { query: collection.query.where(&block) }
97
+ { query: collection.query.where(&) }
98
98
  else
99
99
  { attributes: }
100
100
  end
101
101
  )
102
102
  end
103
103
 
104
- def not_found_error(attributes: nil, &block)
104
+ def not_found_error(attributes: nil, &)
105
105
  Cuprum::Collections::Errors::NotFound.new(
106
- **error_params_for(attributes:, &block)
106
+ **error_params_for(attributes:, &)
107
107
  )
108
108
  end
109
109
 
110
- def not_unique_error(attributes: nil, &block)
110
+ def not_unique_error(attributes: nil, &)
111
111
  Cuprum::Collections::Errors::NotUnique.new(
112
- **error_params_for(attributes:, &block)
112
+ **error_params_for(attributes:, &)
113
113
  )
114
114
  end
115
115
 
@@ -120,14 +120,14 @@ module Cuprum::Collections::Commands
120
120
  require_one_entity(attributes:, entities:, &block)
121
121
  end
122
122
 
123
- def require_one_entity(attributes:, entities:, &block)
123
+ def require_one_entity(attributes:, entities:, &)
124
124
  case entities.count
125
125
  when 0
126
- failure(not_found_error(attributes:, &block))
126
+ failure(not_found_error(attributes:, &))
127
127
  when 1
128
128
  entities.first
129
129
  when 2
130
- failure(not_unique_error(attributes:, &block))
130
+ failure(not_unique_error(attributes:, &))
131
131
  end
132
132
  end
133
133
  end
@@ -5,10 +5,12 @@ require 'cuprum/collections/commands'
5
5
  module Cuprum::Collections::Commands
6
6
  # Shared functionality for defining commands that query the collection.
7
7
  module QueryCommand
8
- # @param query [#call] the query object used to access the collection data.
9
- # @param options [Hash] additional options for the collection.
10
- def initialize(query:, **options)
11
- super(**options)
8
+ # @overload initialize(query:, **options)
9
+ # @param query [#call] the query object used to access the collection
10
+ # data.
11
+ # @param options [Hash] additional options for the collection.
12
+ def initialize(query:, **)
13
+ super(**)
12
14
 
13
15
  @query = query
14
16
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
-
5
3
  require 'cuprum/collections/commands'
6
4
  require 'cuprum/collections/commands/create'
7
5
  require 'cuprum/collections/commands/find_one_matching'
@@ -14,12 +14,13 @@ module Cuprum::Collections::Constraints::Order
14
14
  @instance ||= new
15
15
  end
16
16
 
17
- # @param options [Hash<Symbol, Object>] Configuration options for the
18
- # constraint. Defaults to an empty Hash.
19
- def initialize(**options)
17
+ # @overload initialize(**options)
18
+ # @param options [Hash<Symbol, Object>] Configuration options for the
19
+ # constraint. Defaults to an empty Hash.
20
+ def initialize(**)
20
21
  super(
21
22
  item_type: Cuprum::Collections::Constraints::AttributeName.instance,
22
- **options
23
+ **
23
24
  )
24
25
  end
25
26
  end
@@ -13,14 +13,15 @@ module Cuprum::Collections::Constraints::Order
13
13
  @instance ||= new
14
14
  end
15
15
 
16
- # @param options [Hash<Symbol, Object>] Configuration options for the
17
- # constraint. Defaults to an empty Hash.
18
- def initialize(**options)
16
+ # @overload initialize(**options)
17
+ # @param options [Hash<Symbol, Object>] Configuration options for the
18
+ # constraint. Defaults to an empty Hash.
19
+ def initialize(**)
19
20
  super(
20
21
  key_type: Cuprum::Collections::Constraints::AttributeName.instance,
21
22
  value_type: Cuprum::Collections::Constraints::Order::SortDirection
22
23
  .instance,
23
- **options
24
+ **
24
25
  )
25
26
  end
26
27
  end
@@ -19,8 +19,8 @@ module Cuprum::Collections::Constraints::Order
19
19
  @instance ||= new
20
20
  end
21
21
 
22
- def initialize(**options)
23
- super(*sort_directions, **options)
22
+ def initialize(**)
23
+ super(*sort_directions, **)
24
24
  end
25
25
 
26
26
  private
@@ -41,15 +41,16 @@ module Cuprum::Collections::Constraints
41
41
  @instance ||= new
42
42
  end
43
43
 
44
- # @param options [Hash<Symbol, Object>] Configuration options for the
45
- # constraint. Defaults to an empty Hash.
46
- def initialize(optional: nil, required: nil, **options)
44
+ # @overload initialize(optional: nil, required: nil, **options)
45
+ # @param options [Hash<Symbol, Object>] Configuration options for the
46
+ # constraint. Defaults to an empty Hash.
47
+ def initialize(optional: nil, required: nil, **)
47
48
  super(
48
49
  *ordering_constraints,
49
50
  **resolve_required_option(
50
51
  optional:,
51
52
  required:,
52
- **options
53
+ **
53
54
  )
54
55
  )
55
56
  end
@@ -91,13 +92,14 @@ module Cuprum::Collections::Constraints
91
92
  (errors || Stannum::Errors.new).add(negated_type)
92
93
  end
93
94
 
94
- # Creates a copy of the constraint and updates the copy's options.
95
+ # @overload with_options(**options)
96
+ # Creates a copy of the constraint and updates the copy's options.
95
97
  #
96
- # @param options [Hash] The options to update.
98
+ # @param options [Hash] The options to update.
97
99
  #
98
- # @return [Stannum::Constraints::Base] the copied constraint.
99
- def with_options(**options)
100
- super(**resolve_required_option(**options))
100
+ # @return [Stannum::Constraints::Base] the copied constraint.
101
+ def with_options(**)
102
+ super(**resolve_required_option(**))
101
103
  end
102
104
 
103
105
  private
@@ -8,11 +8,11 @@ require 'cuprum/collections/constraints/attribute_name'
8
8
  module Cuprum::Collections::Constraints
9
9
  # Asserts that the object is a Hash with valid attribute name keys.
10
10
  class QueryHash < Stannum::Constraints::Types::HashType
11
- def initialize(**options)
11
+ def initialize(**)
12
12
  super(
13
13
  allow_empty: true,
14
14
  key_type: attribute_name_constraint,
15
- **options
15
+ **
16
16
  )
17
17
  end
18
18
 
@@ -1,44 +1,110 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'cuprum/collections/errors'
4
+ require 'cuprum/collections/relations/parameters'
4
5
 
5
6
  module Cuprum::Collections::Errors
6
7
  # Abstract base class for failed query errors.
7
8
  class AbstractFindError < Cuprum::Error # rubocop:disable Metrics/ClassLength
8
- PERMITTED_KEYWORDS = %i[
9
+ COLLECTION_KEYWORDS = %i[
10
+ collection
11
+ collection_name
12
+ entity_class
13
+ name
14
+ qualified_name
15
+ ].freeze
16
+ private_constant :COLLECTION_KEYWORDS
17
+
18
+ QUERYING_KEYWORDS = %i[
9
19
  attribute_name
10
20
  attribute_value
11
21
  attributes
12
22
  primary_key
13
23
  query
14
24
  ].freeze
15
- private_constant :PERMITTED_KEYWORDS
25
+ private_constant :QUERYING_KEYWORDS
26
+
27
+ VALID_PARAMETERS = %i[entity_class name qualified_name].freeze
28
+ private_constant :VALID_PARAMETERS
29
+
30
+ class << self
31
+ # Resolves the details about the queried collection.
32
+ #
33
+ # @param params [Hash] the parameters to resolve.
34
+ #
35
+ # @return [Hash] the collection details.
36
+ def resolve_collection(**params) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
37
+ if params[:collection].is_a?(Cuprum::Collections::Collection)
38
+ return collection_details(params[:collection])
39
+ elsif collection_name?(params[:collection])
40
+ return { 'name' => params[:collection].to_s }
41
+ elsif collection_name?(params[:collection_name])
42
+ # @deprecated 0.6.0
43
+ tools.core_tools.deprecate(
44
+ ':collection_name parameter is deprecated',
45
+ message: 'Use the :name parameter instead.'
46
+ )
47
+
48
+ return { 'name' => params[:collection_name].to_s }
49
+ elsif VALID_PARAMETERS.any? { |key| params.key?(key) }
50
+ return Cuprum::Collections::Relations::Parameters
51
+ .resolve_parameters(params)
52
+ .slice(*VALID_PARAMETERS)
53
+ .to_h { |key, value| [key.to_s, value.to_s] }
54
+ end
55
+
56
+ raise ArgumentError, "collection, name or entity class can't be blank"
57
+ end
58
+
59
+ private
60
+
61
+ def collection_details(collection)
62
+ entity_class = collection.entity_class
63
+ entity_class = entity_class.name if entity_class.is_a?(Class)
64
+
65
+ {
66
+ 'entity_class' => entity_class,
67
+ 'name' => collection.name,
68
+ 'qualified_name' => collection.qualified_name
69
+ }
70
+ end
71
+
72
+ def collection_name?(value)
73
+ return false unless value.is_a?(String) || value.is_a?(Symbol)
74
+
75
+ !value.to_s.empty?
76
+ end
77
+
78
+ def tools
79
+ SleepingKingStudios::Tools::Toolbelt.instance
80
+ end
81
+ end
16
82
 
17
- # @overload initialize(attribute_name:, attribute_value:, collection_name:, primary_key: false)
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
83
+ # @overload initialize(attribute_name:, attribute_value:, name:, primary_key: false)
84
+ # @param attribute_name [String] the name of the queried attribute.
85
+ # @param attribute_value [Object] the value of the queried attribute.
86
+ # @param name [String] the name of the collection.
87
+ # @param primary_key [true, false] indicates that the queried attribute is
22
88
  # the primary key for the collection.
23
89
  #
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.
90
+ # @overload initialize(attributes:, name:)
91
+ # @param attributes [Hash<String=>Object>] the queried attributes.
92
+ # @param name [String] the name of the collection.
27
93
  #
28
- # @overload initialize(query:, collection_name:)
29
- # @param collection_name [String] The name of the collection.
94
+ # @overload initialize(query:, name:)
95
+ # @param name [String] the name of the collection.
30
96
  # @param query [Cuprum::Collections::Query] The performed query.
31
- def initialize(collection_name:, **options) # rubocop:disable Metrics/MethodLength
32
- @collection_name = collection_name
97
+ def initialize(**params) # rubocop:disable Metrics/MethodLength
98
+ @collection = self.class.resolve_collection(**params)
99
+ @collection_name = @collection['name']
33
100
  @primary_key = false
34
101
 
35
- resolve_options(**options)
102
+ resolve_options(**params.except(*COLLECTION_KEYWORDS))
36
103
 
37
104
  super(
38
105
  attribute_name:,
39
106
  attribute_value:,
40
107
  attributes:,
41
- collection_name:,
42
108
  message: generate_message,
43
109
  scope:
44
110
  )
@@ -53,12 +119,24 @@ module Cuprum::Collections::Errors
53
119
  # @return [Hash<String=>Object>] The queried attributes.
54
120
  attr_reader :attributes
55
121
 
56
- # @return [String] the name of the collection.
57
- attr_reader :collection_name
122
+ # @return [Hash] the resolved collection details.
123
+ attr_reader :collection
58
124
 
59
125
  # @return [Cuprum::Collections::Scopes::Base] the query scope, if any.
60
126
  attr_reader :scope
61
127
 
128
+ # @return [String] the name of the collection.
129
+ #
130
+ # @deprecated 0.6.0
131
+ def collection_name
132
+ tools.core_tools.deprecate(
133
+ '#collection_name is deprecated',
134
+ message: 'Use the #collection method instead.'
135
+ )
136
+
137
+ collection['name']
138
+ end
139
+
62
140
  # @return [Array<Array>] the details of the query, in scope format.
63
141
  def details # rubocop:disable Metrics/MethodLength
64
142
  if attribute_name
@@ -86,13 +164,13 @@ module Cuprum::Collections::Errors
86
164
 
87
165
  def as_json_data
88
166
  {
89
- 'collection_name' => collection_name,
90
- 'details' => details
167
+ 'collection' => collection,
168
+ 'details' => details
91
169
  }.merge(find_data)
92
170
  end
93
171
 
94
172
  def entity_name
95
- titleize(tools.str.singularize(collection_name))
173
+ titleize(tools.str.singularize(collection['name']))
96
174
  end
97
175
 
98
176
  def find_data # rubocop:disable Metrics/MethodLength
@@ -161,7 +239,7 @@ module Cuprum::Collections::Errors
161
239
  resolve_query_options(**options)
162
240
  else
163
241
  raise ArgumentError,
164
- 'missing keywords :attribute_name, :attribute_value or :attributes ' \
242
+ 'missing keywords :attribute_name, :attribute_value, :attributes, ' \
165
243
  'or :query'
166
244
  end
167
245
  end
@@ -177,7 +255,7 @@ module Cuprum::Collections::Errors
177
255
  def validate_keywords(extra_keywords:) # rubocop:disable Metrics/MethodLength
178
256
  return if extra_keywords.empty?
179
257
 
180
- ambiguous_keywords = extra_keywords & PERMITTED_KEYWORDS
258
+ ambiguous_keywords = extra_keywords & QUERYING_KEYWORDS
181
259
 
182
260
  if ambiguous_keywords.empty?
183
261
  raise ArgumentError,
@@ -15,7 +15,7 @@ module Cuprum::Collections::Errors
15
15
  # that were assigned to the entity.
16
16
  # @param valid_attributes [Array<String>] The names of valid attributes for
17
17
  # the entity.
18
- def initialize(entity_class:, extra_attributes:, valid_attributes:)
18
+ def initialize(extra_attributes:, valid_attributes:, entity_class: nil)
19
19
  @entity_class = entity_class
20
20
  @extra_attributes = extra_attributes
21
21
  @valid_attributes = valid_attributes
@@ -42,14 +42,14 @@ module Cuprum::Collections::Errors
42
42
 
43
43
  def as_json_data
44
44
  {
45
- 'entity_class' => entity_class.name,
45
+ 'entity_class' => entity_class&.name,
46
46
  'extra_attributes' => extra_attributes,
47
47
  'valid_attributes' => valid_attributes
48
48
  }
49
49
  end
50
50
 
51
51
  def default_message
52
- "invalid attributes for #{entity_class.name}: " \
52
+ "invalid attributes for #{entity_class&.name || 'an entity'}: " \
53
53
  "#{extra_attributes.join(', ')}"
54
54
  end
55
55
  end
@@ -13,7 +13,7 @@ module Cuprum::Collections::Errors
13
13
  # @param entity_class [Class] The class of the assigned entity.
14
14
  # @param errors [Stannum::Errors] The errors generated when validating the
15
15
  # entity.
16
- def initialize(entity_class:, errors:)
16
+ def initialize(errors:, entity_class: nil)
17
17
  @entity_class = entity_class
18
18
  @errors = errors
19
19
 
@@ -34,13 +34,13 @@ module Cuprum::Collections::Errors
34
34
 
35
35
  def as_json_data
36
36
  {
37
- 'entity_class' => entity_class.name,
37
+ 'entity_class' => entity_class&.name,
38
38
  'errors' => format_errors
39
39
  }
40
40
  end
41
41
 
42
42
  def default_message
43
- "#{entity_class.name} failed validation"
43
+ "#{entity_class&.name || 'an entity'} failed validation"
44
44
  end
45
45
 
46
46
  def format_errors
@@ -11,7 +11,7 @@ module Cuprum::Collections::Errors
11
11
  TYPE = 'cuprum.collections.errors.missing_default_contract'
12
12
 
13
13
  # @param entity_class [Class] The class of the assigned entity.
14
- def initialize(entity_class:)
14
+ def initialize(entity_class: nil)
15
15
  @entity_class = entity_class
16
16
 
17
17
  super(
@@ -26,12 +26,20 @@ module Cuprum::Collections::Errors
26
26
  private
27
27
 
28
28
  def as_json_data
29
- { 'entity_class' => entity_class.name }
29
+ { 'entity_class' => entity_class&.name }
30
30
  end
31
31
 
32
32
  def default_message
33
- "attempted to validate a #{entity_class.name}, but " \
34
- "#{entity_class.name} does not define a default contract"
33
+ "attempted to validate #{entity_name}, but " \
34
+ "#{entity_class_name} does not define a default contract"
35
+ end
36
+
37
+ def entity_class_name
38
+ entity_class&.name || 'the entity class'
39
+ end
40
+
41
+ def entity_name
42
+ entity_class ? "a #{entity_class.name}" : 'an entity'
35
43
  end
36
44
  end
37
45
  end