mongoid 5.1.5 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
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)