mongoid 5.1.5 → 5.2.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 (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/config/locales/en.yml +15 -0
  5. data/lib/mongoid.rb +5 -0
  6. data/lib/mongoid/attributes/dynamic.rb +3 -3
  7. data/lib/mongoid/clients/factory.rb +2 -0
  8. data/lib/mongoid/config.rb +1 -0
  9. data/lib/mongoid/config/options.rb +1 -1
  10. data/lib/mongoid/contextual/aggregable/mongo.rb +0 -1
  11. data/lib/mongoid/contextual/map_reduce.rb +20 -97
  12. data/lib/mongoid/contextual/memory.rb +1 -0
  13. data/lib/mongoid/contextual/mongo.rb +20 -15
  14. data/lib/mongoid/criteria.rb +2 -0
  15. data/lib/mongoid/document.rb +1 -0
  16. data/lib/mongoid/errors.rb +1 -0
  17. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +20 -0
  18. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  19. data/lib/mongoid/extensions.rb +1 -0
  20. data/lib/mongoid/extensions/decimal128.rb +39 -0
  21. data/lib/mongoid/fields/localized.rb +8 -3
  22. data/lib/mongoid/indexable/validators/options.rb +2 -1
  23. data/lib/mongoid/persistable/deletable.rb +3 -7
  24. data/lib/mongoid/persistable/settable.rb +3 -1
  25. data/lib/mongoid/query_cache.rb +24 -2
  26. data/lib/mongoid/relations/accessors.rb +1 -1
  27. data/lib/mongoid/relations/builders.rb +2 -2
  28. data/lib/mongoid/relations/eager.rb +2 -2
  29. data/lib/mongoid/relations/reflections.rb +5 -3
  30. data/lib/mongoid/relations/touchable.rb +1 -1
  31. data/lib/mongoid/scopable.rb +1 -1
  32. data/lib/mongoid/version.rb +1 -1
  33. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +6 -2
  34. data/spec/app/models/band.rb +1 -0
  35. data/spec/config/mongoid.yml +5 -0
  36. data/spec/mongoid/clients/factory_spec.rb +8 -0
  37. data/spec/mongoid/clients_spec.rb +78 -1
  38. data/spec/mongoid/config_spec.rb +31 -0
  39. data/spec/mongoid/contextual/atomic_spec.rb +342 -76
  40. data/spec/mongoid/contextual/map_reduce_spec.rb +111 -119
  41. data/spec/mongoid/contextual/memory_spec.rb +316 -56
  42. data/spec/mongoid/contextual/mongo_spec.rb +391 -11
  43. data/spec/mongoid/criteria_spec.rb +21 -2
  44. data/spec/mongoid/extensions/decimal128_spec.rb +44 -0
  45. data/spec/mongoid/extensions/time_spec.rb +2 -2
  46. data/spec/mongoid/fields/localized_spec.rb +91 -0
  47. data/spec/mongoid/indexable_spec.rb +44 -0
  48. data/spec/mongoid/persistable/settable_spec.rb +44 -0
  49. data/spec/mongoid/query_cache_spec.rb +86 -0
  50. data/spec/mongoid/relations/cyclic_spec.rb +22 -0
  51. data/spec/mongoid/relations/referenced/many_spec.rb +11 -0
  52. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +11 -0
  53. data/spec/mongoid/relations/reflections_spec.rb +9 -9
  54. data/spec/mongoid/scopable_spec.rb +12 -0
  55. data/spec/spec_helper.rb +9 -0
  56. metadata +26 -16
  57. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: abf3bc71acef310e6e22c9900a173ef44adcffe9
4
- data.tar.gz: 3178495b48b2377e77929352b9349c02adee7017
3
+ metadata.gz: c45686b0e53c4e404c5f52563b399c2ae3909dce
4
+ data.tar.gz: aea6ea222ae4e97af3ec984a7cb185cce8de966a
5
5
  SHA512:
6
- metadata.gz: 16106f196625909b1bbefd3bea0ab5e7b3397cd8055108c01c7f5b1ae7dc485810a9fa78ab5975b3794e2db8a2fe2b82d9c8d3e18b69e762f2ff994727397eba
7
- data.tar.gz: e08c0e8efaa17427d5d3e329322dd367b72a44eb5f3a5c9e2d0d1c9bf5d4bebcae313ee155dbb5f78578cd98a767f2a7e78fad5747c87221176da465321384ab
6
+ metadata.gz: 033d87560a04cdcae0e2353117eccaa5f14ab4ea273e9bc491cd4cef659ae3488008f17894161375d6910c7be9533d249722eda57a556b8d388419761863366e
7
+ data.tar.gz: df6a8a161d146fd07a8ddc9867b0105c8f5285273770b169cd280b47c211d54ae31b7bb1ca96f27c35cc43a5e7ccf9e12485592722522efae0541f43d5ac42cf
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -76,6 +76,12 @@ en:
76
76
  resolution: "For access to the collection that the embedded document is
77
77
  in, use %{klass}#_root.collection, or do not attempt to persist an
78
78
  embedded document without a parent set."
79
+ in_memory_collation_not_supported:
80
+ message: "A collation option cannot be applied when querying documents in-memory."
81
+ summary: "The query being run against documents in memory has a collation option set.
82
+ A collation option is only supported if the query is executed on a MongoDB server
83
+ with version >= 3.4."
84
+ resolution: "Remove the collation option from the query."
79
85
  invalid_config_option:
80
86
  message: "Invalid configuration option: %{name}."
81
87
  summary: "A invalid configuration option was provided in your
@@ -134,9 +140,18 @@ en:
134
140
  \_\_min: 1\n
135
141
  \_\_max: 1\n
136
142
  \_\_bits: 26\n
143
+ \_\_key: 26\n
137
144
  \_\_bucket_size : 1\n
145
+ \_\_sphere_version : 1\n
146
+ \_\_text_version : 1\n
147
+ \_\_version : 1\n
138
148
  \_\_weights: { content: 1, title: 2 }\n
139
149
  \_\_expire_after_seconds: number_of_seconds\n
150
+ \_\_partial_filter_expression\n
151
+ \_\_storage_engine\n
152
+ \_\_language_override\n
153
+ \_\_default_language\n
154
+ \_\_collation\n
140
155
  Valid types are: 1, -1, '2d', '2dsphere', 'geoHaystack', 'text', 'hashed'\n\n
141
156
  Example:\n
142
157
  \_\_class Band\n
data/lib/mongoid.rb CHANGED
@@ -36,6 +36,11 @@ module Mongoid
36
36
  extend Loggable
37
37
  extend self
38
38
 
39
+ # A string added to the platform details of Ruby driver client handshake documents.
40
+ #
41
+ # @since 6.1.0
42
+ PLATFORM_DETAILS = "mongoid-#{VERSION}".freeze
43
+
39
44
  # The minimum MongoDB version supported.
40
45
  MONGODB_VERSION = "2.4.0"
41
46
 
@@ -37,7 +37,7 @@ module Mongoid
37
37
  # @since 4.0.0
38
38
  def define_dynamic_reader(name)
39
39
  return unless name.valid_method_name?
40
- class_eval <<-READER
40
+ class_eval <<-READER, __FILE__, __LINE__ + 1
41
41
  def #{name}
42
42
  attribute_will_change!(#{name.inspect})
43
43
  read_attribute(#{name.inspect})
@@ -56,7 +56,7 @@ module Mongoid
56
56
  #
57
57
  # @since 4.0.0
58
58
  def define_dynamic_before_type_cast_reader(name)
59
- class_eval <<-READER
59
+ class_eval <<-READER, __FILE__, __LINE__ + 1
60
60
  def #{name}_before_type_cast
61
61
  attribute_will_change!(#{name.inspect})
62
62
  read_attribute_before_type_cast(#{name.inspect})
@@ -77,7 +77,7 @@ module Mongoid
77
77
  def define_dynamic_writer(name)
78
78
  return unless name.valid_method_name?
79
79
 
80
- class_eval <<-WRITER
80
+ class_eval <<-WRITER, __FILE__, __LINE__ + 1
81
81
  def #{name}=(value)
82
82
  write_attribute(#{name.inspect}, value)
83
83
  end
@@ -71,6 +71,8 @@ module Mongoid
71
71
  def options(configuration)
72
72
  config = configuration.dup
73
73
  options = config.delete(:options) || {}
74
+ options[:platform] = PLATFORM_DETAILS
75
+ options[:app_name] = Mongoid::Config.app_name if Mongoid::Config.app_name
74
76
  options.reject{ |k, v| k == :hosts }.to_hash.symbolize_keys!
75
77
  end
76
78
  end
@@ -25,6 +25,7 @@ module Mongoid
25
25
  option :use_activesupport_time_zone, default: true
26
26
  option :use_utc, default: false
27
27
  option :log_level, default: :info
28
+ option :app_name, default: nil
28
29
 
29
30
  # Has Mongoid been configured? This is checking that at least a valid
30
31
  # client config exists.
@@ -31,7 +31,7 @@ module Mongoid
31
31
  def option(name, options = {})
32
32
  defaults[name] = settings[name] = options[:default]
33
33
 
34
- class_eval <<-RUBY
34
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
35
35
  def #{name}
36
36
  settings[#{name.inspect}]
37
37
  end
@@ -124,7 +124,6 @@ module Mongoid
124
124
  def pipeline(field)
125
125
  db_field = "$#{database_field_name(field)}"
126
126
  pipeline = []
127
- pipeline << { "$match" => criteria.selector }
128
127
  pipeline << { "$match" => criteria.exists(field => true).selector }
129
128
  pipeline << { "$sort" => criteria.options[:sort] } if criteria.options[:sort]
130
129
  pipeline << { "$skip" => criteria.options[:skip] } if criteria.options[:skip]
@@ -32,12 +32,13 @@ module Mongoid
32
32
  #
33
33
  # @since 3.0.0
34
34
  def each
35
+ validate_out!
35
36
  if block_given?
36
- documents.each do |doc|
37
+ @map_reduce.each do |doc|
37
38
  yield doc
38
39
  end
39
40
  else
40
- to_enum
41
+ @map_reduce.to_enum
41
42
  end
42
43
  end
43
44
 
@@ -64,7 +65,7 @@ module Mongoid
64
65
  #
65
66
  # @since 3.0.0
66
67
  def finalize(function)
67
- command[:finalize] = function
68
+ @map_reduce = @map_reduce.finalize(function)
68
69
  self
69
70
  end
70
71
 
@@ -79,10 +80,9 @@ module Mongoid
79
80
  #
80
81
  # @since 3.0.0
81
82
  def initialize(collection, criteria, map, reduce)
82
- @collection, @criteria = collection, criteria
83
- command[:mapreduce] = collection.name.to_s
84
- command[:map], command[:reduce] = map, reduce
85
- apply_criteria_options
83
+ @collection = collection
84
+ @criteria = criteria
85
+ @map_reduce = @criteria.view.map_reduce(map, reduce)
86
86
  end
87
87
 
88
88
  # Get the number of documents that were input into the map/reduce.
@@ -106,7 +106,7 @@ module Mongoid
106
106
  #
107
107
  # @since 3.0.0
108
108
  def js_mode
109
- command[:jsMode] = true
109
+ @map_reduce = @map_reduce.js_mode(true)
110
110
  self
111
111
  end
112
112
 
@@ -134,7 +134,7 @@ module Mongoid
134
134
  normalized.update_values do |value|
135
135
  value.is_a?(::Symbol) ? value.to_s : value
136
136
  end
137
- command[:out] = normalized
137
+ @map_reduce = @map_reduce.out(normalized)
138
138
  self
139
139
  end
140
140
 
@@ -159,8 +159,12 @@ module Mongoid
159
159
  #
160
160
  # @since 3.0.0
161
161
  def raw
162
- results
162
+ validate_out!
163
+ cmd = command
164
+ opts = { read: cmd.delete(:read).options } if cmd[:read]
165
+ @map_reduce.database.command(cmd, opts || {}).first
163
166
  end
167
+ alias :results :raw
164
168
 
165
169
  # Execute the map/reduce, returning the raw output.
166
170
  # Useful when you don't care about map/reduce's ouptut.
@@ -196,7 +200,7 @@ module Mongoid
196
200
  #
197
201
  # @since 3.0.0
198
202
  def scope(object)
199
- command[:scope] = object
203
+ @map_reduce = @map_reduce.scope(object)
200
204
  self
201
205
  end
202
206
 
@@ -232,95 +236,14 @@ module Mongoid
232
236
  }
233
237
  end
234
238
 
235
- private
236
-
237
- # Apply criteria specific options - query, sort, limit.
238
- #
239
- # @api private
240
- #
241
- # @example Apply the criteria options
242
- # map_reduce.apply_criteria_options
243
- #
244
- # @return [ nil ] Nothing.
245
- #
246
- # @since 3.0.0
247
- def apply_criteria_options
248
- command[:query] = criteria.selector
249
- if sort = criteria.options[:sort]
250
- command[:sort] = sort
251
- end
252
- if limit = criteria.options[:limit]
253
- command[:limit] = limit
254
- end
239
+ def command
240
+ @map_reduce.send(:map_reduce_spec)[:selector]
255
241
  end
256
242
 
257
- # Get the result documents from the map/reduce. If the output was inline
258
- # then we grab them from the results key. If the output was a temp
259
- # collection then we need to execute a find on that collection.
260
- #
261
- # @api private
262
- #
263
- # @example Get the documents.
264
- # map_reduce.documents
265
- #
266
- # @return [ Array, Cursor ] The documents.
267
- #
268
- # @since 3.0.0
269
- def documents
270
- return results["results"] if results.has_key?("results")
271
- view = client[output_collection].find
272
- view.no_cursor_timeout if criteria.options[:timeout] == false
273
- view
274
- end
275
-
276
- # Get the collection that the map/reduce results were stored in.
277
- #
278
- # @api private
279
- #
280
- # @example Get the output collection.
281
- # map_reduce.output_collection
282
- #
283
- # @return [ Symbol, String ] The output collection.
284
- #
285
- # @since 3.0.0
286
- def output_collection
287
- command[:out].values.first
288
- end
289
-
290
- # Execute the map/reduce command and get the results.
291
- #
292
- # @api private
293
- #
294
- # @example Get the results.
295
- # map_reduce.results
296
- #
297
- # @return [ Hash ] The results of the command.
298
- #
299
- # @since 3.0.0
300
- def results
301
- raise Errors::NoMapReduceOutput.new(command) unless command[:out]
302
- @results ||= __client__.command(command).first
303
- end
243
+ private
304
244
 
305
- # Get the client with the proper consistency.
306
- #
307
- # @api private
308
- #
309
- # @note We can use eventual if the output is set to inline.
310
- #
311
- # @example Get the client.
312
- # map_reduce.__client__
313
- #
314
- # @return [ Mongo::Client ] The client with consistency set.
315
- #
316
- # @since 3.0.15
317
- def __client__
318
- if command[:out][:inline] != 1
319
- # @todo: close
320
- client.with(read: { mode: :primary })
321
- else
322
- client
323
- end
245
+ def validate_out!
246
+ raise Errors::NoMapReduceOutput.new({}) unless @map_reduce.out
324
247
  end
325
248
  end
326
249
  end
@@ -373,6 +373,7 @@ module Mongoid
373
373
  #
374
374
  # @since 3.0.0
375
375
  def apply_options
376
+ raise Errors::InMemoryCollationNotSupported.new if criteria.options[:collation]
376
377
  skip(criteria.options[:skip]).limit(criteria.options[:limit])
377
378
  end
378
379
 
@@ -18,7 +18,18 @@ module Mongoid
18
18
  # Options constant.
19
19
  #
20
20
  # @since 5.0.0
21
- OPTIONS = [ :hint, :limit, :skip, :sort, :batch_size, :max_scan, :snapshot, :comment, :read ].freeze
21
+ OPTIONS = [ :hint,
22
+ :limit,
23
+ :skip,
24
+ :sort,
25
+ :batch_size,
26
+ :max_scan,
27
+ :snapshot,
28
+ :comment,
29
+ :read,
30
+ :cursor_type,
31
+ :collation
32
+ ].freeze
22
33
 
23
34
  # @attribute [r] view The Mongo collection view.
24
35
  attr_reader :view
@@ -68,9 +79,7 @@ module Mongoid
68
79
  #
69
80
  # @since 3.0.0
70
81
  def delete
71
- self.count.tap do
72
- view.delete_many
73
- end
82
+ view.delete_many.deleted_count
74
83
  end
75
84
  alias :delete_all :delete
76
85
 
@@ -83,11 +92,10 @@ module Mongoid
83
92
  #
84
93
  # @since 3.0.0
85
94
  def destroy
86
- destroyed = self.count
87
- each do |doc|
95
+ each.inject(0) do |count, doc|
88
96
  doc.destroy
97
+ count += 1
89
98
  end
90
- destroyed
91
99
  end
92
100
  alias :destroy_all :destroy
93
101
 
@@ -551,12 +559,6 @@ module Mongoid
551
559
  if criteria.options[:timeout] == false
552
560
  @view = view.no_cursor_timeout
553
561
  end
554
- if criteria.options[:cursor_type]
555
- # @todo: update to use #cursor_type method on view when driver 2.3 is released.
556
- # See RUBY-1080
557
- @view = view.clone
558
- @view.options.merge!(cursor_type: criteria.options[:cursor_type])
559
- end
560
562
  end
561
563
 
562
564
  # Apply an option.
@@ -653,6 +655,7 @@ module Mongoid
653
655
  # @since 3.0.0
654
656
  def documents_for_iteration
655
657
  return documents if cached? && !documents.empty?
658
+ return view unless eager_loadable?
656
659
  docs = view.map{ |doc| Factory.from_db(klass, doc, criteria.options[:fields]) }
657
660
  eager_load(docs)
658
661
  end
@@ -670,8 +673,10 @@ module Mongoid
670
673
  #
671
674
  # @since 3.0.0
672
675
  def yield_document(document, &block)
673
- yield(document)
674
- documents.push(document) if cacheable?
676
+ doc = document.respond_to?(:_id) ?
677
+ document : Factory.from_db(klass, document, criteria.options[:fields])
678
+ yield(doc)
679
+ documents.push(doc) if cacheable?
675
680
  end
676
681
  end
677
682
  end
@@ -193,6 +193,8 @@ module Mongoid
193
193
  # @since 1.0.0
194
194
  def initialize(klass)
195
195
  @klass = klass
196
+ @embedded = nil
197
+ @none = nil
196
198
  klass ? super(klass.aliased_fields, klass.fields) : super({}, {})
197
199
  end
198
200
 
@@ -101,6 +101,7 @@ module Mongoid
101
101
  #
102
102
  # @since 1.0.0
103
103
  def initialize(attrs = nil)
104
+ @__parent = nil
104
105
  _building do
105
106
  @new_record = true
106
107
  @attributes ||= {}
@@ -5,6 +5,7 @@ require "mongoid/errors/callback"
5
5
  require "mongoid/errors/document_not_destroyed"
6
6
  require "mongoid/errors/document_not_found"
7
7
  require "mongoid/errors/eager_load"
8
+ require "mongoid/errors/in_memory_collation_not_supported"
8
9
  require "mongoid/errors/invalid_collection"
9
10
  require "mongoid/errors/invalid_config_option"
10
11
  require "mongoid/errors/invalid_field"
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Errors
4
+
5
+ # This error is raised when attempting to do a query with a
6
+ # collation on documents in memory.
7
+ class InMemoryCollationNotSupported < MongoidError
8
+
9
+ # Create the new error.
10
+ #
11
+ # @example Create the new unsupported collation error.
12
+ # InMemoryCollationNotSupported.new
13
+ #
14
+ # @since 5.2.0
15
+ def initialize
16
+ super(compose_message("in_memory_collation_not_supported"))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -19,7 +19,7 @@ module Mongoid
19
19
  # @return [ String ] The composed message.
20
20
  #
21
21
  # @since 3.0.0
22
- def compose_message(key, attributes)
22
+ def compose_message(key, attributes = {})
23
23
  @problem = translate_problem(key, attributes)
24
24
  @summary = translate_summary(key, attributes)
25
25
  @resolution = translate_resolution(key, attributes)