mongoid 7.2.4 → 7.3.2

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 (157) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +16 -0
  5. data/lib/config/locales/en.yml +2 -2
  6. data/lib/mongoid.rb +1 -0
  7. data/lib/mongoid/association/accessors.rb +13 -1
  8. data/lib/mongoid/association/constrainable.rb +1 -1
  9. data/lib/mongoid/association/depending.rb +4 -4
  10. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  11. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  12. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +11 -4
  13. data/lib/mongoid/association/nested/many.rb +1 -1
  14. data/lib/mongoid/association/nested/one.rb +4 -2
  15. data/lib/mongoid/association/proxy.rb +7 -2
  16. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  17. data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
  18. data/lib/mongoid/association/referenced/has_many/proxy.rb +3 -3
  19. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  20. data/lib/mongoid/attributes.rb +24 -13
  21. data/lib/mongoid/attributes/projector.rb +120 -0
  22. data/lib/mongoid/cacheable.rb +2 -2
  23. data/lib/mongoid/clients.rb +1 -1
  24. data/lib/mongoid/clients/factory.rb +22 -8
  25. data/lib/mongoid/config.rb +19 -2
  26. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  27. data/lib/mongoid/copyable.rb +1 -1
  28. data/lib/mongoid/criteria.rb +5 -6
  29. data/lib/mongoid/criteria/findable.rb +1 -1
  30. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  31. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  32. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  33. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  34. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  35. data/lib/mongoid/document.rb +1 -15
  36. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  37. data/lib/mongoid/evolvable.rb +1 -1
  38. data/lib/mongoid/extensions/boolean.rb +1 -2
  39. data/lib/mongoid/extensions/false_class.rb +1 -1
  40. data/lib/mongoid/extensions/hash.rb +2 -2
  41. data/lib/mongoid/extensions/true_class.rb +1 -1
  42. data/lib/mongoid/fields.rb +43 -5
  43. data/lib/mongoid/inspectable.rb +1 -1
  44. data/lib/mongoid/interceptable.rb +1 -1
  45. data/lib/mongoid/matcher.rb +7 -0
  46. data/lib/mongoid/matcher/bits.rb +41 -0
  47. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  48. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  49. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  50. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  51. data/lib/mongoid/matcher/expression.rb +4 -0
  52. data/lib/mongoid/matcher/field_operator.rb +6 -0
  53. data/lib/mongoid/matcher/mod.rb +17 -0
  54. data/lib/mongoid/matcher/type.rb +99 -0
  55. data/lib/mongoid/persistable/deletable.rb +1 -2
  56. data/lib/mongoid/persistable/destroyable.rb +8 -2
  57. data/lib/mongoid/persistable/updatable.rb +27 -2
  58. data/lib/mongoid/query_cache.rb +35 -29
  59. data/lib/mongoid/selectable.rb +5 -7
  60. data/lib/mongoid/shardable.rb +21 -5
  61. data/lib/mongoid/touchable.rb +23 -4
  62. data/lib/mongoid/version.rb +1 -1
  63. data/spec/integration/associations/embeds_many_spec.rb +44 -0
  64. data/spec/integration/associations/has_one_spec.rb +48 -0
  65. data/spec/integration/criteria/date_field_spec.rb +1 -1
  66. data/spec/integration/document_spec.rb +9 -0
  67. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  68. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  69. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  70. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  71. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  72. data/spec/integration/matcher_operator_data/in.yml +16 -0
  73. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  74. data/spec/integration/matcher_operator_data/type.yml +70 -0
  75. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  76. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  77. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  78. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  79. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  80. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  81. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  82. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  83. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  84. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  85. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  86. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  87. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  88. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  89. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  90. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  91. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  92. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  93. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  94. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  95. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  96. data/spec/lite_spec_helper.rb +2 -0
  97. data/spec/mongoid/association/depending_spec.rb +391 -352
  98. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +17 -4
  99. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  100. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +42 -8
  101. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  102. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  103. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  104. data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
  105. data/spec/mongoid/atomic/paths_spec.rb +64 -12
  106. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  107. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  108. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  109. data/spec/mongoid/attributes_spec.rb +98 -6
  110. data/spec/mongoid/clients/factory_spec.rb +48 -0
  111. data/spec/mongoid/clients/options_spec.rb +2 -0
  112. data/spec/mongoid/config_spec.rb +32 -0
  113. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  114. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  115. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  116. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  117. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  118. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
  119. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  120. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  121. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  122. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  123. data/spec/mongoid/criteria_spec.rb +4 -275
  124. data/spec/mongoid/document_spec.rb +13 -13
  125. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  126. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  127. data/spec/mongoid/extensions/string_spec.rb +5 -5
  128. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  129. data/spec/mongoid/fields/localized_spec.rb +4 -4
  130. data/spec/mongoid/fields_spec.rb +4 -4
  131. data/spec/mongoid/inspectable_spec.rb +12 -4
  132. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  133. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  134. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  135. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  136. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  137. data/spec/mongoid/reloadable_spec.rb +18 -1
  138. data/spec/mongoid/shardable_spec.rb +44 -0
  139. data/spec/mongoid/touchable_spec.rb +104 -16
  140. data/spec/mongoid/touchable_spec_models.rb +52 -0
  141. data/spec/mongoid/validatable_spec.rb +1 -1
  142. data/spec/spec_helper.rb +6 -2
  143. data/spec/support/client_registry.rb +9 -0
  144. data/spec/support/models/address.rb +4 -0
  145. data/spec/support/models/bolt.rb +8 -0
  146. data/spec/support/models/hole.rb +13 -0
  147. data/spec/support/models/mop.rb +0 -1
  148. data/spec/support/models/nut.rb +8 -0
  149. data/spec/support/models/person.rb +15 -0
  150. data/spec/support/models/sealer.rb +8 -0
  151. data/spec/support/models/shirt.rb +12 -0
  152. data/spec/support/models/spacer.rb +8 -0
  153. data/spec/support/models/threadlocker.rb +8 -0
  154. data/spec/support/models/washer.rb +8 -0
  155. metadata +112 -4
  156. metadata.gz.sig +0 -0
  157. data/spec/support/cluster_config.rb +0 -158
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5841b5911599ef45f1b350592ec4995d2a044e723b14ef03e16cf7508449d396
4
- data.tar.gz: c6276353b2e03f57c166c96f7bbcee0362a391f91e19c294a7c76a3c3dad3fe6
3
+ metadata.gz: 27ef7fb0ba8610ab6cd4cf814a5a47361fe909247a85535c807d90dbf70c1563
4
+ data.tar.gz: fe110c6f5439f985325f3df374bfc87fa5c9133eb97cac501dd9166b8d45cf60
5
5
  SHA512:
6
- metadata.gz: 277666610a79f335d47add6f4fb24ecb4a47ea6a245f7d28cec43258876ba469463460a98a1eeeeee5f200a5ab58ed6da7c81dec3be9d617d5ba970194949e09
7
- data.tar.gz: a564a89c548c566a230d03ad69f6323280c071a04f3754f7a2abdeb1da883a4fa6856e7b9e091fdfb0325017f160eb81c875169da54bc04c865e2499f4cd31e9
6
+ metadata.gz: 3f963e5e7fb3a7705d36ce9a6d24fb09106ca2ccca52d1a2cf24ddbf9a98773206d315374d4ecc40ad6a208be75ad0de5e44a6d43285faa3304ec641d91de3fa
7
+ data.tar.gz: 167e2188b8801cb0a4eb15ec98727e3f331eab9f0588923f80f5f3cf2e29eec8b9cf6a01ace242d6412ea578a9fa7e4de309278a309c0d84b5cc07091f74828f
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/Rakefile CHANGED
@@ -66,6 +66,22 @@ task :ci do
66
66
  spec_organizer.run
67
67
  end
68
68
 
69
+ task :bucket, %i(buckets) do |task, args|
70
+ buckets = args[:buckets]
71
+ buckets = if buckets.nil? || buckets.empty?
72
+ [nil]
73
+ else
74
+ buckets.split(':').map do |bucket|
75
+ if bucket.empty?
76
+ nil
77
+ else
78
+ bucket.to_sym
79
+ end
80
+ end
81
+ end
82
+ spec_organizer.run_buckets(*buckets)
83
+ end
84
+
69
85
  task :default => :spec
70
86
 
71
87
  desc "Generate all documentation"
@@ -578,9 +578,9 @@ en:
578
578
  resolution: "Try persisting the document with valid data or remove
579
579
  the validations."
580
580
  delete_restriction:
581
- message: "Cannot delete %{document} because of dependent '%{relation}'."
581
+ message: "Cannot destroy %{document} because of dependent '%{relation}'."
582
582
  summary: "When defining '%{relation}' with a :dependent => :restrict_with_error,
583
- Mongoid will raise an error when attempting to delete the
583
+ Mongoid will raise an error when attempting to destroy the
584
584
  %{document} when the child '%{relation}' still has documents in it."
585
585
  resolution: "Don't attempt to delete the parent %{document} when
586
586
  it has children, or change the dependent option on the association."
data/lib/mongoid.rb CHANGED
@@ -6,6 +6,7 @@ require "support/ruby_version"
6
6
  require "forwardable"
7
7
  require "time"
8
8
  require "set"
9
+ require "ruby2_keywords"
9
10
 
10
11
  require "active_support"
11
12
  require "active_support/core_ext"
@@ -121,6 +121,9 @@ module Mongoid
121
121
  # (embedded) association with the given key, or nil if no projection
122
122
  # is to be performed.
123
123
  #
124
+ # Also returns nil if exclusionary projection was requested but it does
125
+ # not exclude the field of the association.
126
+ #
124
127
  # For example, if __selected_fields is {'a' => 1, 'b.c' => 2, 'b.c.f' => 3},
125
128
  # and assoc_key is 'b', return value would be {'c' => 2, 'c.f' => 3}.
126
129
  #
@@ -132,6 +135,15 @@ module Mongoid
132
135
  def _mongoid_filter_selected_fields(assoc_key)
133
136
  return nil unless __selected_fields
134
137
 
138
+ # If the list of fields was specified using #without instead of #only
139
+ # and the provided list does not include the association, any of its
140
+ # fields should be allowed.
141
+ if __selected_fields.values.all? { |v| v == 0 } &&
142
+ __selected_fields.keys.none? { |k| k.split('.', 2).first == assoc_key }
143
+ then
144
+ return nil
145
+ end
146
+
135
147
  projecting_assoc = false
136
148
 
137
149
  filtered = {}
@@ -300,7 +312,7 @@ module Mongoid
300
312
  ids_method = "#{association.name.to_s.singularize}_ids"
301
313
  association.inverse_class.tap do |klass|
302
314
  klass.re_define_method(ids_method) do
303
- send(association.name).only(:id).map(&:id)
315
+ send(association.name).only(:_id).map(&:_id)
304
316
  end
305
317
  end
306
318
  end
@@ -36,7 +36,7 @@ module Mongoid
36
36
 
37
37
  def convert_polymorphic(object)
38
38
  if object.is_a?(Mongoid::Document)
39
- object.id
39
+ object._id
40
40
  else
41
41
  BSON::ObjectId.mongoize(object)
42
42
  end
@@ -78,13 +78,13 @@ module Mongoid
78
78
  # the appropriate strategy to perform the operation.
79
79
  #
80
80
  # @example Execute cascades.
81
- # document.apply_delete_dependencies!
81
+ # document.apply_destroy_dependencies!
82
82
  #
83
83
  # @since 2.0.0.rc.1
84
- def apply_delete_dependencies!
84
+ def apply_destroy_dependencies!
85
85
  self.class._all_dependents.each do |association|
86
- if association.try(:dependent)
87
- send("_dependent_#{association.dependent}!", association)
86
+ if dependent = association.try(:dependent)
87
+ send("_dependent_#{dependent}!", association)
88
88
  end
89
89
  end
90
90
  end
@@ -329,7 +329,7 @@ module Mongoid
329
329
  self.path = doc.atomic_path unless path
330
330
  execute_callback :before_remove, doc
331
331
  unless _assigning?
332
- doc.apply_delete_dependencies!
332
+ doc.apply_destroy_dependencies!
333
333
  doc.run_before_callbacks(:destroy) if method == :destroy
334
334
  end
335
335
  _target.delete_one(doc)
@@ -26,7 +26,7 @@ module Mongoid
26
26
  :autobuild,
27
27
  :cyclic,
28
28
  :polymorphic,
29
- :touch
29
+ :touch,
30
30
  ].freeze
31
31
 
32
32
  # The complete list of valid options for this association, including
@@ -83,8 +83,15 @@ module Mongoid
83
83
 
84
84
  alias :new :build
85
85
 
86
- # Clear the association. Will delete the documents from the db if they are
87
- # already persisted.
86
+ # Clear the association. Will delete the documents from the db
87
+ # if they are already persisted.
88
+ #
89
+ # If the host document is not persisted but its _id matches a
90
+ # persisted document, calling #clear on an association will remove
91
+ # the association's documents from the database even though the
92
+ # set of documents in the application (as loaded in the host)
93
+ # is different from what is in the database, and the host may
94
+ # not contain any persisted documents in the association either.
88
95
  #
89
96
  # @example Clear the association.
90
97
  # person.addresses.clear
@@ -332,7 +339,7 @@ module Mongoid
332
339
  private
333
340
 
334
341
  def object_already_related?(document)
335
- _target.any? { |existing| existing.id && existing === document }
342
+ _target.any? { |existing| existing._id && existing === document }
336
343
  end
337
344
 
338
345
  # Appends the document to the target array, updating the index on the
@@ -415,7 +422,7 @@ module Mongoid
415
422
  # @param [ Proc ] block Optional block to pass.
416
423
  #
417
424
  # @return [ Criteria, Object ] A Criteria or return value from the target.
418
- def method_missing(name, *args, &block)
425
+ ruby2_keywords def method_missing(name, *args, &block)
419
426
  return super if _target.respond_to?(name)
420
427
  klass.send(:with_scope, criteria) do
421
428
  criteria.public_send(name, *args, &block)
@@ -181,7 +181,7 @@ module Mongoid
181
181
  first = existing.first
182
182
  converted = first ? convert_id(first.class, id) : id
183
183
 
184
- if existing.where(id: converted).exists?
184
+ if existing.where(_id: converted).exists?
185
185
  # document exists in association
186
186
  doc = existing.find(converted)
187
187
  if destroyable?(attrs)
@@ -71,7 +71,8 @@ module Mongoid
71
71
  #
72
72
  # @since 2.0.0
73
73
  def acceptable_id?
74
- id = convert_id(existing.class, attributes[:id])
74
+ id = association.klass.extract_id_field(attributes)
75
+ id = convert_id(existing.class, id)
75
76
  existing._id == id || id.nil? || (existing._id != id && update_only?)
76
77
  end
77
78
 
@@ -84,7 +85,8 @@ module Mongoid
84
85
  #
85
86
  # @since 2.0.0
86
87
  def delete?
87
- destroyable? && !attributes[:id].nil?
88
+ id = association.klass.extract_id_field(attributes)
89
+ destroyable? && !id.nil?
88
90
  end
89
91
 
90
92
  # Can the existing association potentially be destroyed?
@@ -16,7 +16,7 @@ module Mongoid
16
16
  # We undefine most methods to get them sent through to the target.
17
17
  instance_methods.each do |method|
18
18
  undef_method(method) unless
19
- method =~ /\A(__.*|send|object_id|equal\?|respond_to\?|tap|public_send|extend_proxy|extend_proxies)\z/
19
+ method =~ /\A(?:__.*|send|object_id|equal\?|respond_to\?|respond_to_missing\?|tap|public_send|extend_proxy|extend_proxies)\z/
20
20
  end
21
21
 
22
22
  include Threaded::Lifecycle
@@ -133,10 +133,15 @@ module Mongoid
133
133
  # @param [ String, Symbol ] name The name of the method.
134
134
  # @param [ Array ] args The arguments passed to the method.
135
135
  #
136
- def method_missing(name, *args, &block)
136
+ ruby2_keywords def method_missing(name, *args, &block)
137
137
  _target.send(name, *args, &block)
138
138
  end
139
139
 
140
+ # @api private
141
+ ruby2_keywords def respond_to_missing?(name, *args)
142
+ _target.respond_to?(name, *args)
143
+ end
144
+
140
145
  # When the base document illegally references an embedded document this
141
146
  # error will get raised.
142
147
  #
@@ -63,8 +63,8 @@ module Mongoid
63
63
  self.before_callback_halted = false
64
64
  else
65
65
  __autosaving__ do
66
- if relation = ivar(association.name)
67
- Array(relation).each do |doc|
66
+ if assoc_value = ivar(association.name)
67
+ Array(assoc_value).each do |doc|
68
68
  doc.with(persistence_context) do |d|
69
69
  d.save
70
70
  end
@@ -5,544 +5,542 @@ module Mongoid
5
5
  module Association
6
6
  module Referenced
7
7
  class HasMany
8
- module Targets
9
-
10
- # This class is the wrapper for all referenced associations that have a
11
- # target that can be a criteria or array of _loaded documents. This
12
- # handles both cases or a combination of the two.
13
- class Enumerable
14
- extend Forwardable
15
- include ::Enumerable
16
-
17
- # The three main instance variables are collections of documents.
18
- #
19
- # @attribute [rw] _added Documents that have been appended.
20
- # @attribute [rw] _loaded Persisted documents that have been _loaded.
21
- # @attribute [rw] _unloaded A criteria representing persisted docs.
22
- attr_accessor :_added, :_loaded, :_unloaded
23
-
24
- def_delegators [], :is_a?, :kind_of?
25
-
26
- # Check if the enumerable is equal to the other object.
27
- #
28
- # @example Check equality.
29
- # enumerable == []
30
- #
31
- # @param [ Enumerable ] other The other enumerable.
32
- #
33
- # @return [ true, false ] If the objects are equal.
34
- #
35
- # @since 2.1.0
36
- def ==(other)
37
- return false unless other.respond_to?(:entries)
38
- entries == other.entries
39
- end
40
8
 
41
- # Check equality of the enumerable against the provided object for case
42
- # statements.
43
- #
44
- # @example Check case equality.
45
- # enumerable === Array
46
- #
47
- # @param [ Object ] other The object to check.
48
- #
49
- # @return [ true, false ] If the objects are equal in a case.
50
- #
51
- # @since 3.1.4
52
- def ===(other)
53
- other.class == Class ? (Array == other || Enumerable == other) : self == other
54
- end
9
+ # This class is the wrapper for all referenced associations that have a
10
+ # target that can be a criteria or array of _loaded documents. This
11
+ # handles both cases or a combination of the two.
12
+ class Enumerable
13
+ extend Forwardable
14
+ include ::Enumerable
15
+
16
+ # The three main instance variables are collections of documents.
17
+ #
18
+ # @attribute [rw] _added Documents that have been appended.
19
+ # @attribute [rw] _loaded Persisted documents that have been _loaded.
20
+ # @attribute [rw] _unloaded A criteria representing persisted docs.
21
+ attr_accessor :_added, :_loaded, :_unloaded
22
+
23
+ def_delegators [], :is_a?, :kind_of?
24
+
25
+ # Check if the enumerable is equal to the other object.
26
+ #
27
+ # @example Check equality.
28
+ # enumerable == []
29
+ #
30
+ # @param [ Enumerable ] other The other enumerable.
31
+ #
32
+ # @return [ true, false ] If the objects are equal.
33
+ #
34
+ # @since 2.1.0
35
+ def ==(other)
36
+ return false unless other.respond_to?(:entries)
37
+ entries == other.entries
38
+ end
55
39
 
56
- # Append a document to the enumerable.
57
- #
58
- # @example Append the document.
59
- # enumerable << document
60
- #
61
- # @param [ Document ] document The document to append.
62
- #
63
- # @return [ Document ] The document.
64
- #
65
- # @since 2.1.0
66
- def <<(document)
67
- _added[document._id] = document
68
- self
69
- end
40
+ # Check equality of the enumerable against the provided object for case
41
+ # statements.
42
+ #
43
+ # @example Check case equality.
44
+ # enumerable === Array
45
+ #
46
+ # @param [ Object ] other The object to check.
47
+ #
48
+ # @return [ true, false ] If the objects are equal in a case.
49
+ #
50
+ # @since 3.1.4
51
+ def ===(other)
52
+ other.class == Class ? (Array == other || Enumerable == other) : self == other
53
+ end
70
54
 
71
- alias :push :<<
72
-
73
- # Clears out all the documents in this enumerable. If passed a block it
74
- # will yield to each document that is in memory.
75
- #
76
- # @example Clear out the enumerable.
77
- # enumerable.clear
78
- #
79
- # @example Clear out the enumerable with a block.
80
- # enumerable.clear do |doc|
81
- # doc.unbind
82
- # end
83
- #
84
- # @return [ Array<Document> ] The cleared out _added docs.
85
- #
86
- # @since 2.1.0
87
- def clear
88
- if block_given?
89
- in_memory { |doc| yield(doc) }
90
- end
91
- _loaded.clear and _added.clear
92
- end
55
+ # Append a document to the enumerable.
56
+ #
57
+ # @example Append the document.
58
+ # enumerable << document
59
+ #
60
+ # @param [ Document ] document The document to append.
61
+ #
62
+ # @return [ Document ] The document.
63
+ #
64
+ # @since 2.1.0
65
+ def <<(document)
66
+ _added[document._id] = document
67
+ self
68
+ end
93
69
 
94
- # Clones each document in the enumerable.
95
- #
96
- # @note This loads all documents into memory.
97
- #
98
- # @example Clone the enumerable.
99
- # enumerable.clone
100
- #
101
- # @return [ Array<Document> ] An array clone of the enumerable.
102
- #
103
- # @since 2.1.6
104
- def clone
105
- collect { |doc| doc.clone }
70
+ alias :push :<<
71
+
72
+ # Clears out all the documents in this enumerable. If passed a block it
73
+ # will yield to each document that is in memory.
74
+ #
75
+ # @example Clear out the enumerable.
76
+ # enumerable.clear
77
+ #
78
+ # @example Clear out the enumerable with a block.
79
+ # enumerable.clear do |doc|
80
+ # doc.unbind
81
+ # end
82
+ #
83
+ # @return [ Array<Document> ] The cleared out _added docs.
84
+ #
85
+ # @since 2.1.0
86
+ def clear
87
+ if block_given?
88
+ in_memory { |doc| yield(doc) }
106
89
  end
90
+ _loaded.clear and _added.clear
91
+ end
92
+
93
+ # Clones each document in the enumerable.
94
+ #
95
+ # @note This loads all documents into memory.
96
+ #
97
+ # @example Clone the enumerable.
98
+ # enumerable.clone
99
+ #
100
+ # @return [ Array<Document> ] An array clone of the enumerable.
101
+ #
102
+ # @since 2.1.6
103
+ def clone
104
+ collect { |doc| doc.clone }
105
+ end
107
106
 
108
- # Delete the supplied document from the enumerable.
109
- #
110
- # @example Delete the document.
111
- # enumerable.delete(document)
112
- #
113
- # @param [ Document ] document The document to delete.
114
- #
115
- # @return [ Document ] The deleted document.
116
- #
117
- # @since 2.1.0
118
- def delete(document)
119
- doc = (_loaded.delete(document._id) || _added.delete(document._id))
120
- unless doc
121
- if _unloaded && _unloaded.where(_id: document._id).exists?
122
- yield(document) if block_given?
123
- return document
124
- end
107
+ # Delete the supplied document from the enumerable.
108
+ #
109
+ # @example Delete the document.
110
+ # enumerable.delete(document)
111
+ #
112
+ # @param [ Document ] document The document to delete.
113
+ #
114
+ # @return [ Document ] The deleted document.
115
+ #
116
+ # @since 2.1.0
117
+ def delete(document)
118
+ doc = (_loaded.delete(document._id) || _added.delete(document._id))
119
+ unless doc
120
+ if _unloaded && _unloaded.where(_id: document._id).exists?
121
+ yield(document) if block_given?
122
+ return document
125
123
  end
126
- yield(doc) if block_given?
127
- doc
128
124
  end
125
+ yield(doc) if block_given?
126
+ doc
127
+ end
129
128
 
130
- # Deletes every document in the enumerable for where the block returns
131
- # true.
132
- #
133
- # @note This operation loads all documents from the database.
134
- #
135
- # @example Delete all matching documents.
136
- # enumerable.delete_if do |doc|
137
- # dod._id == _id
138
- # end
139
- #
140
- # @return [ Array<Document> ] The remaining docs.
141
- #
142
- # @since 2.1.0
143
- def delete_if(&block)
144
- load_all!
145
- deleted = in_memory.select(&block)
146
- deleted.each do |doc|
147
- _loaded.delete(doc._id)
148
- _added.delete(doc._id)
149
- end
150
- self
129
+ # Deletes every document in the enumerable for where the block returns
130
+ # true.
131
+ #
132
+ # @note This operation loads all documents from the database.
133
+ #
134
+ # @example Delete all matching documents.
135
+ # enumerable.delete_if do |doc|
136
+ # dod._id == _id
137
+ # end
138
+ #
139
+ # @return [ Array<Document> ] The remaining docs.
140
+ #
141
+ # @since 2.1.0
142
+ def delete_if(&block)
143
+ load_all!
144
+ deleted = in_memory.select(&block)
145
+ deleted.each do |doc|
146
+ _loaded.delete(doc._id)
147
+ _added.delete(doc._id)
151
148
  end
149
+ self
150
+ end
152
151
 
153
- # Iterating over this enumerable has to handle a few different
154
- # scenarios.
155
- #
156
- # If the enumerable has its criteria _loaded into memory then it yields
157
- # to all the _loaded docs and all the _added docs.
158
- #
159
- # If the enumerable has not _loaded the criteria then it iterates over
160
- # the cursor while loading the documents and then iterates over the
161
- # _added docs.
162
- #
163
- # If no block is passed then it returns an enumerator containing all
164
- # docs.
165
- #
166
- # @example Iterate over the enumerable.
167
- # enumerable.each do |doc|
168
- # puts doc
169
- # end
170
- #
171
- # @example return an enumerator containing all the docs
172
- #
173
- # a = enumerable.each
174
- #
175
- # @return [ true ] That the enumerable is now _loaded.
176
- #
177
- # @since 2.1.0
178
- def each
179
- unless block_given?
180
- return to_enum
181
- end
182
- if _loaded?
183
- _loaded.each_pair do |id, doc|
184
- document = _added.delete(doc._id) || doc
185
- set_base(document)
186
- yield(document)
187
- end
188
- else
189
- unloaded_documents.each do |doc|
190
- document = _added.delete(doc._id) || _loaded.delete(doc._id) || doc
191
- _loaded[document._id] = document
192
- set_base(document)
193
- yield(document)
194
- end
152
+ # Iterating over this enumerable has to handle a few different
153
+ # scenarios.
154
+ #
155
+ # If the enumerable has its criteria _loaded into memory then it yields
156
+ # to all the _loaded docs and all the _added docs.
157
+ #
158
+ # If the enumerable has not _loaded the criteria then it iterates over
159
+ # the cursor while loading the documents and then iterates over the
160
+ # _added docs.
161
+ #
162
+ # If no block is passed then it returns an enumerator containing all
163
+ # docs.
164
+ #
165
+ # @example Iterate over the enumerable.
166
+ # enumerable.each do |doc|
167
+ # puts doc
168
+ # end
169
+ #
170
+ # @example return an enumerator containing all the docs
171
+ #
172
+ # a = enumerable.each
173
+ #
174
+ # @return [ true ] That the enumerable is now _loaded.
175
+ #
176
+ # @since 2.1.0
177
+ def each
178
+ unless block_given?
179
+ return to_enum
180
+ end
181
+ if _loaded?
182
+ _loaded.each_pair do |id, doc|
183
+ document = _added.delete(doc._id) || doc
184
+ set_base(document)
185
+ yield(document)
195
186
  end
196
- _added.each_pair do |id, doc|
197
- yield(doc)
187
+ else
188
+ unloaded_documents.each do |doc|
189
+ document = _added.delete(doc._id) || _loaded.delete(doc._id) || doc
190
+ _loaded[document._id] = document
191
+ set_base(document)
192
+ yield(document)
198
193
  end
199
- @executed = true
200
194
  end
201
-
202
- # Is the enumerable empty? Will determine if the count is zero based on
203
- # whether or not it is _loaded.
204
- #
205
- # @example Is the enumerable empty?
206
- # enumerable.empty?
207
- #
208
- # @return [ true, false ] If the enumerable is empty.
209
- #
210
- # @since 2.1.0
211
- def empty?
212
- if _loaded?
213
- in_memory.count == 0
214
- else
215
- _unloaded.count + _added.count == 0
216
- end
195
+ _added.each_pair do |id, doc|
196
+ yield(doc)
217
197
  end
198
+ @executed = true
199
+ end
218
200
 
219
- # Returns whether the association has any documents, optionally
220
- # subject to the provided filters.
221
- #
222
- # This method returns true if the association has any persisted
223
- # documents and if it has any not yet persisted documents.
224
- #
225
- # If the association is already loaded, this method inspects the
226
- # loaded documents and does not query the database. If the
227
- # association is not loaded, the argument-less and block-less
228
- # version does not load the association; the other versions
229
- # (that delegate to Enumerable) may or may not load the association
230
- # completely depending on whether it is iterated to completion.
231
- #
232
- # This method can take a parameter and a block. The behavior with
233
- # either the paramater or the block is delegated to the standard
234
- # library Enumerable module.
235
- #
236
- # Note that when Enumerable's any? method is invoked with both
237
- # a block and a pattern, it only uses the pattern.
238
- #
239
- # @param [ Object ] condition The condition that documents
240
- # must satisfy. See Enumerable documentation for details.
241
- #
242
- # @return [ true, false ] If the association has any documents.
243
- def any?(*args)
244
- return super if args.any? || block_given?
245
-
246
- if _loaded?
247
- in_memory.length > 0
248
- else
249
- _unloaded.exists? || _added.length > 0
250
- end
201
+ # Is the enumerable empty? Will determine if the count is zero based on
202
+ # whether or not it is _loaded.
203
+ #
204
+ # @example Is the enumerable empty?
205
+ # enumerable.empty?
206
+ #
207
+ # @return [ true, false ] If the enumerable is empty.
208
+ #
209
+ # @since 2.1.0
210
+ def empty?
211
+ if _loaded?
212
+ in_memory.count == 0
213
+ else
214
+ _unloaded.count + _added.count == 0
251
215
  end
216
+ end
252
217
 
253
- # Get the first document in the enumerable. Will check the persisted
254
- # documents first. Does not load the entire enumerable.
255
- #
256
- # @example Get the first document.
257
- # enumerable.first
258
- #
259
- # @note Automatically adding a sort on _id when no other sort is
260
- # defined on the criteria has the potential to cause bad performance issues.
261
- # If you experience unexpected poor performance when using #first or #last,
262
- # use the option { id_sort: :none }.
263
- # Be aware that #first/#last won't guarantee order in this case.
264
- #
265
- # @param [ Hash ] opts The options for the query returning the first document.
266
- #
267
- # @option opts [ :none ] :id_sort Don't apply a sort on _id.
268
- #
269
- # @return [ Document ] The first document found.
270
- #
271
- # @since 2.1.0
272
- def first(opts = {})
273
- _loaded.try(:values).try(:first) ||
274
- _added[(ul = _unloaded.try(:first, opts)).try(:id)] ||
275
- ul ||
276
- _added.values.try(:first)
218
+ # Returns whether the association has any documents, optionally
219
+ # subject to the provided filters.
220
+ #
221
+ # This method returns true if the association has any persisted
222
+ # documents and if it has any not yet persisted documents.
223
+ #
224
+ # If the association is already loaded, this method inspects the
225
+ # loaded documents and does not query the database. If the
226
+ # association is not loaded, the argument-less and block-less
227
+ # version does not load the association; the other versions
228
+ # (that delegate to Enumerable) may or may not load the association
229
+ # completely depending on whether it is iterated to completion.
230
+ #
231
+ # This method can take a parameter and a block. The behavior with
232
+ # either the paramater or the block is delegated to the standard
233
+ # library Enumerable module.
234
+ #
235
+ # Note that when Enumerable's any? method is invoked with both
236
+ # a block and a pattern, it only uses the pattern.
237
+ #
238
+ # @param [ Object ] condition The condition that documents
239
+ # must satisfy. See Enumerable documentation for details.
240
+ #
241
+ # @return [ true, false ] If the association has any documents.
242
+ def any?(*args)
243
+ return super if args.any? || block_given?
244
+
245
+ if _loaded?
246
+ in_memory.length > 0
247
+ else
248
+ _unloaded.exists? || _added.length > 0
277
249
  end
250
+ end
278
251
 
279
- # Initialize the new enumerable either with a criteria or an array.
280
- #
281
- # @example Initialize the enumerable with a criteria.
282
- # Enumberable.new(Post.where(:person_id => id))
283
- #
284
- # @example Initialize the enumerable with an array.
285
- # Enumerable.new([ post ])
286
- #
287
- # @param [ Criteria, Array<Document> ] target The wrapped object.
288
- #
289
- # @since 2.1.0
290
- def initialize(target, base = nil, association = nil)
291
- @_base = base
292
- @_association = association
293
- if target.is_a?(Criteria)
294
- @_added, @executed, @_loaded, @_unloaded = {}, false, {}, target
295
- else
296
- @_added, @executed = {}, true
297
- @_loaded = target.inject({}) do |_target, doc|
298
- _target[doc._id] = doc if doc
299
- _target
300
- end
252
+ # Get the first document in the enumerable. Will check the persisted
253
+ # documents first. Does not load the entire enumerable.
254
+ #
255
+ # @example Get the first document.
256
+ # enumerable.first
257
+ #
258
+ # @note Automatically adding a sort on _id when no other sort is
259
+ # defined on the criteria has the potential to cause bad performance issues.
260
+ # If you experience unexpected poor performance when using #first or #last,
261
+ # use the option { id_sort: :none }.
262
+ # Be aware that #first/#last won't guarantee order in this case.
263
+ #
264
+ # @param [ Hash ] opts The options for the query returning the first document.
265
+ #
266
+ # @option opts [ :none ] :id_sort Don't apply a sort on _id.
267
+ #
268
+ # @return [ Document ] The first document found.
269
+ #
270
+ # @since 2.1.0
271
+ def first(opts = {})
272
+ _loaded.try(:values).try(:first) ||
273
+ _added[(ul = _unloaded.try(:first, opts)).try(:_id)] ||
274
+ ul ||
275
+ _added.values.try(:first)
276
+ end
277
+
278
+ # Initialize the new enumerable either with a criteria or an array.
279
+ #
280
+ # @example Initialize the enumerable with a criteria.
281
+ # Enumberable.new(Post.where(:person_id => id))
282
+ #
283
+ # @example Initialize the enumerable with an array.
284
+ # Enumerable.new([ post ])
285
+ #
286
+ # @param [ Criteria, Array<Document> ] target The wrapped object.
287
+ #
288
+ # @since 2.1.0
289
+ def initialize(target, base = nil, association = nil)
290
+ @_base = base
291
+ @_association = association
292
+ if target.is_a?(Criteria)
293
+ @_added, @executed, @_loaded, @_unloaded = {}, false, {}, target
294
+ else
295
+ @_added, @executed = {}, true
296
+ @_loaded = target.inject({}) do |_target, doc|
297
+ _target[doc._id] = doc if doc
298
+ _target
301
299
  end
302
300
  end
301
+ end
303
302
 
304
- # Does the target include the provided document?
305
- #
306
- # @example Does the target include the document?
307
- # enumerable.include?(document)
308
- #
309
- # @param [ Document ] doc The document to check.
310
- #
311
- # @return [ true, false ] If the document is in the target.
312
- #
313
- # @since 3.0.0
314
- def include?(doc)
315
- return super unless _unloaded
316
- _unloaded.where(_id: doc._id).exists? || _added.has_key?(doc._id)
317
- end
303
+ # Does the target include the provided document?
304
+ #
305
+ # @example Does the target include the document?
306
+ # enumerable.include?(document)
307
+ #
308
+ # @param [ Document ] doc The document to check.
309
+ #
310
+ # @return [ true, false ] If the document is in the target.
311
+ #
312
+ # @since 3.0.0
313
+ def include?(doc)
314
+ return super unless _unloaded
315
+ _unloaded.where(_id: doc._id).exists? || _added.has_key?(doc._id)
316
+ end
318
317
 
319
- # Inspection will just inspect the entries for nice array-style
320
- # printing.
321
- #
322
- # @example Inspect the enumerable.
323
- # enumerable.inspect
324
- #
325
- # @return [ String ] The inspected enum.
326
- #
327
- # @since 2.1.0
328
- def inspect
329
- entries.inspect
330
- end
318
+ # Inspection will just inspect the entries for nice array-style
319
+ # printing.
320
+ #
321
+ # @example Inspect the enumerable.
322
+ # enumerable.inspect
323
+ #
324
+ # @return [ String ] The inspected enum.
325
+ #
326
+ # @since 2.1.0
327
+ def inspect
328
+ entries.inspect
329
+ end
331
330
 
332
- # Return all the documents in the enumerable that have been _loaded or
333
- # _added.
334
- #
335
- # @note When passed a block it yields to each document.
336
- #
337
- # @example Get the in memory docs.
338
- # enumerable.in_memory
339
- #
340
- # @return [ Array<Document> ] The in memory docs.
341
- #
342
- # @since 2.1.0
343
- def in_memory
344
- docs = (_loaded.values + _added.values)
345
- docs.each do |doc|
346
- yield(doc) if block_given?
347
- end
331
+ # Return all the documents in the enumerable that have been _loaded or
332
+ # _added.
333
+ #
334
+ # @note When passed a block it yields to each document.
335
+ #
336
+ # @example Get the in memory docs.
337
+ # enumerable.in_memory
338
+ #
339
+ # @return [ Array<Document> ] The in memory docs.
340
+ #
341
+ # @since 2.1.0
342
+ def in_memory
343
+ docs = (_loaded.values + _added.values)
344
+ docs.each do |doc|
345
+ yield(doc) if block_given?
348
346
  end
347
+ end
349
348
 
350
- # Get the last document in the enumerable. Will check the new
351
- # documents first. Does not load the entire enumerable.
352
- #
353
- # @example Get the last document.
354
- # enumerable.last
355
- #
356
- # @note Automatically adding a sort on _id when no other sort is
357
- # defined on the criteria has the potential to cause bad performance issues.
358
- # If you experience unexpected poor performance when using #first or #last,
359
- # use the option { id_sort: :none }.
360
- # Be aware that #first/#last won't guarantee order in this case.
361
- #
362
- # @param [ Hash ] opts The options for the query returning the first document.
363
- #
364
- # @option opts [ :none ] :id_sort Don't apply a sort on _id.
365
- #
366
- # @return [ Document ] The last document found.
367
- #
368
- # @since 2.1.0
369
- def last(opts = {})
370
- _added.values.try(:last) ||
371
- _loaded.try(:values).try(:last) ||
372
- _added[(ul = _unloaded.try(:last, opts)).try(:id)] ||
373
- ul
374
- end
349
+ # Get the last document in the enumerable. Will check the new
350
+ # documents first. Does not load the entire enumerable.
351
+ #
352
+ # @example Get the last document.
353
+ # enumerable.last
354
+ #
355
+ # @note Automatically adding a sort on _id when no other sort is
356
+ # defined on the criteria has the potential to cause bad performance issues.
357
+ # If you experience unexpected poor performance when using #first or #last,
358
+ # use the option { id_sort: :none }.
359
+ # Be aware that #first/#last won't guarantee order in this case.
360
+ #
361
+ # @param [ Hash ] opts The options for the query returning the first document.
362
+ #
363
+ # @option opts [ :none ] :id_sort Don't apply a sort on _id.
364
+ #
365
+ # @return [ Document ] The last document found.
366
+ #
367
+ # @since 2.1.0
368
+ def last(opts = {})
369
+ _added.values.try(:last) ||
370
+ _loaded.try(:values).try(:last) ||
371
+ _added[(ul = _unloaded.try(:last, opts)).try(:_id)] ||
372
+ ul
373
+ end
375
374
 
376
- # Loads all the documents in the enumerable from the database.
377
- #
378
- # @example Load all the documents.
379
- # enumerable.load_all!
380
- #
381
- # @return [ true ] That the enumerable is _loaded.
382
- #
383
- # @since 2.1.0
384
- alias :load_all! :entries
385
-
386
- # Has the enumerable been _loaded? This will be true if the criteria has
387
- # been executed or we manually load the entire thing.
388
- #
389
- # @example Is the enumerable _loaded?
390
- # enumerable._loaded?
391
- #
392
- # @return [ true, false ] If the enumerable has been _loaded.
393
- #
394
- # @since 2.1.0
395
- def _loaded?
396
- !!@executed
397
- end
375
+ # Loads all the documents in the enumerable from the database.
376
+ #
377
+ # @example Load all the documents.
378
+ # enumerable.load_all!
379
+ #
380
+ # @return [ true ] That the enumerable is _loaded.
381
+ #
382
+ # @since 2.1.0
383
+ alias :load_all! :entries
384
+
385
+ # Has the enumerable been _loaded? This will be true if the criteria has
386
+ # been executed or we manually load the entire thing.
387
+ #
388
+ # @example Is the enumerable _loaded?
389
+ # enumerable._loaded?
390
+ #
391
+ # @return [ true, false ] If the enumerable has been _loaded.
392
+ #
393
+ # @since 2.1.0
394
+ def _loaded?
395
+ !!@executed
396
+ end
398
397
 
399
- # Provides the data needed to Marshal.dump an enumerable proxy.
400
- #
401
- # @example Dump the proxy.
402
- # Marshal.dump(proxy)
403
- #
404
- # @return [ Array<Object> ] The dumped data.
405
- #
406
- # @since 3.0.15
407
- def marshal_dump
408
- [_added, _loaded, _unloaded, @executed]
409
- end
398
+ # Provides the data needed to Marshal.dump an enumerable proxy.
399
+ #
400
+ # @example Dump the proxy.
401
+ # Marshal.dump(proxy)
402
+ #
403
+ # @return [ Array<Object> ] The dumped data.
404
+ #
405
+ # @since 3.0.15
406
+ def marshal_dump
407
+ [_added, _loaded, _unloaded, @executed]
408
+ end
410
409
 
411
- # Loads the data needed to Marshal.load an enumerable proxy.
412
- #
413
- # @example Load the proxy.
414
- # Marshal.load(proxy)
415
- #
416
- # @return [ Array<Object> ] The dumped data.
417
- #
418
- # @since 3.0.15
419
- def marshal_load(data)
420
- @_added, @_loaded, @_unloaded, @executed = data
421
- end
410
+ # Loads the data needed to Marshal.load an enumerable proxy.
411
+ #
412
+ # @example Load the proxy.
413
+ # Marshal.load(proxy)
414
+ #
415
+ # @return [ Array<Object> ] The dumped data.
416
+ #
417
+ # @since 3.0.15
418
+ def marshal_load(data)
419
+ @_added, @_loaded, @_unloaded, @executed = data
420
+ end
422
421
 
423
- # Reset the enumerable back to its persisted state.
424
- #
425
- # @example Reset the enumerable.
426
- # enumerable.reset
427
- #
428
- # @return [ false ] Always false.
429
- #
430
- # @since 2.1.0
431
- def reset
432
- _loaded.clear
433
- _added.clear
434
- @executed = false
435
- end
422
+ # Reset the enumerable back to its persisted state.
423
+ #
424
+ # @example Reset the enumerable.
425
+ # enumerable.reset
426
+ #
427
+ # @return [ false ] Always false.
428
+ #
429
+ # @since 2.1.0
430
+ def reset
431
+ _loaded.clear
432
+ _added.clear
433
+ @executed = false
434
+ end
436
435
 
437
- # Resets the underlying unloaded criteria object with a new one. Used
438
- # my HABTM associations to keep the underlying array in sync.
439
- #
440
- # @example Reset the unloaded documents.
441
- # enumerable.reset_unloaded(criteria)
442
- #
443
- # @param [ Criteria ] criteria The criteria to replace with.
444
- #
445
- # @since 3.0.14
446
- def reset_unloaded(criteria)
447
- @_unloaded = criteria if _unloaded.is_a?(Criteria)
448
- end
436
+ # Resets the underlying unloaded criteria object with a new one. Used
437
+ # my HABTM associations to keep the underlying array in sync.
438
+ #
439
+ # @example Reset the unloaded documents.
440
+ # enumerable.reset_unloaded(criteria)
441
+ #
442
+ # @param [ Criteria ] criteria The criteria to replace with.
443
+ #
444
+ # @since 3.0.14
445
+ def reset_unloaded(criteria)
446
+ @_unloaded = criteria if _unloaded.is_a?(Criteria)
447
+ end
449
448
 
450
- # Does this enumerable respond to the provided method?
451
- #
452
- # @example Does the enumerable respond to the method?
453
- # enumerable.respond_to?(:sum)
454
- #
455
- # @param [ String, Symbol ] name The name of the method.
456
- # @param [ true, false ] include_private Whether to include private
457
- # methods.
458
- #
459
- # @return [ true, false ] Whether the enumerable responds.
460
- #
461
- # @since 2.1.0
462
- def respond_to?(name, include_private = false)
463
- [].respond_to?(name, include_private) || super
464
- end
449
+ # Does this enumerable respond to the provided method?
450
+ #
451
+ # @example Does the enumerable respond to the method?
452
+ # enumerable.respond_to?(:sum)
453
+ #
454
+ # @param [ String, Symbol ] name The name of the method.
455
+ # @param [ true, false ] include_private Whether to include private
456
+ # methods.
457
+ #
458
+ # @return [ true, false ] Whether the enumerable responds.
459
+ #
460
+ # @since 2.1.0
461
+ def respond_to?(name, include_private = false)
462
+ [].respond_to?(name, include_private) || super
463
+ end
465
464
 
466
- # Gets the total size of this enumerable. This is a combination of all
467
- # the persisted and unpersisted documents.
468
- #
469
- # @example Get the size.
470
- # enumerable.size
471
- #
472
- # @return [ Integer ] The size of the enumerable.
473
- #
474
- # @since 2.1.0
475
- def size
476
- count = (_unloaded ? _unloaded.count : _loaded.count)
477
- if count.zero?
478
- count + _added.count
479
- else
480
- count + _added.values.count { |d| d.new_record? }
481
- end
465
+ # Gets the total size of this enumerable. This is a combination of all
466
+ # the persisted and unpersisted documents.
467
+ #
468
+ # @example Get the size.
469
+ # enumerable.size
470
+ #
471
+ # @return [ Integer ] The size of the enumerable.
472
+ #
473
+ # @since 2.1.0
474
+ def size
475
+ count = (_unloaded ? _unloaded.count : _loaded.count)
476
+ if count.zero?
477
+ count + _added.count
478
+ else
479
+ count + _added.values.count { |d| d.new_record? }
482
480
  end
481
+ end
483
482
 
484
- alias :length :size
485
-
486
- # Send #to_json to the entries.
487
- #
488
- # @example Get the enumerable as json.
489
- # enumerable.to_json
490
- #
491
- # @param [ Hash ] options Optional parameters.
492
- #
493
- # @return [ String ] The entries all _loaded as a string.
494
- #
495
- # @since 2.2.0
496
- def to_json(options = {})
497
- entries.to_json(options)
498
- end
483
+ alias :length :size
484
+
485
+ # Send #to_json to the entries.
486
+ #
487
+ # @example Get the enumerable as json.
488
+ # enumerable.to_json
489
+ #
490
+ # @param [ Hash ] options Optional parameters.
491
+ #
492
+ # @return [ String ] The entries all _loaded as a string.
493
+ #
494
+ # @since 2.2.0
495
+ def to_json(options = {})
496
+ entries.to_json(options)
497
+ end
499
498
 
500
- # Send #as_json to the entries, without encoding.
501
- #
502
- # @example Get the enumerable as json.
503
- # enumerable.as_json
504
- #
505
- # @param [ Hash ] options Optional parameters.
506
- #
507
- # @return [ Hash ] The entries all _loaded as a hash.
508
- #
509
- # @since 2.2.0
510
- def as_json(options = {})
511
- entries.as_json(options)
512
- end
499
+ # Send #as_json to the entries, without encoding.
500
+ #
501
+ # @example Get the enumerable as json.
502
+ # enumerable.as_json
503
+ #
504
+ # @param [ Hash ] options Optional parameters.
505
+ #
506
+ # @return [ Hash ] The entries all _loaded as a hash.
507
+ #
508
+ # @since 2.2.0
509
+ def as_json(options = {})
510
+ entries.as_json(options)
511
+ end
513
512
 
514
- # Return all the unique documents in the enumerable.
515
- #
516
- # @note This operation loads all documents from the database.
517
- #
518
- # @example Get all the unique documents.
519
- # enumerable.uniq
520
- #
521
- # @return [ Array<Document> ] The unique documents.
522
- #
523
- # @since 2.1.0
524
- def uniq
525
- entries.uniq
526
- end
513
+ # Return all the unique documents in the enumerable.
514
+ #
515
+ # @note This operation loads all documents from the database.
516
+ #
517
+ # @example Get all the unique documents.
518
+ # enumerable.uniq
519
+ #
520
+ # @return [ Array<Document> ] The unique documents.
521
+ #
522
+ # @since 2.1.0
523
+ def uniq
524
+ entries.uniq
525
+ end
527
526
 
528
- private
527
+ private
529
528
 
530
- def set_base(document)
531
- if @_association.is_a?(Referenced::HasMany)
532
- document.set_relation(@_association.inverse, @_base) if @_association
533
- end
529
+ def set_base(document)
530
+ if @_association.is_a?(Referenced::HasMany)
531
+ document.set_relation(@_association.inverse, @_base) if @_association
534
532
  end
533
+ end
535
534
 
536
- def method_missing(name, *args, &block)
537
- entries.send(name, *args, &block)
538
- end
535
+ ruby2_keywords def method_missing(name, *args, &block)
536
+ entries.send(name, *args, &block)
537
+ end
539
538
 
540
- def unloaded_documents
541
- if _unloaded.selector._mongoid_unsatisfiable_criteria?
542
- []
543
- else
544
- _unloaded
545
- end
539
+ def unloaded_documents
540
+ if _unloaded.selector._mongoid_unsatisfiable_criteria?
541
+ []
542
+ else
543
+ _unloaded
546
544
  end
547
545
  end
548
546
  end