mongoid 3.0.23 → 3.1.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 (95) hide show
  1. data/CHANGELOG.md +253 -9
  2. data/LICENSE +1 -1
  3. data/README.md +4 -1
  4. data/lib/config/locales/en.yml +7 -6
  5. data/lib/mongoid.rb +18 -1
  6. data/lib/mongoid/atomic.rb +22 -20
  7. data/lib/mongoid/atomic/paths/embedded.rb +19 -5
  8. data/lib/mongoid/atomic/paths/root.rb +1 -1
  9. data/lib/mongoid/atomic/positionable.rb +73 -0
  10. data/lib/mongoid/attributes.rb +63 -1
  11. data/lib/mongoid/callbacks.rb +58 -4
  12. data/lib/mongoid/components.rb +8 -3
  13. data/lib/mongoid/config.rb +71 -23
  14. data/lib/mongoid/contextual.rb +2 -1
  15. data/lib/mongoid/contextual/aggregable/mongo.rb +27 -63
  16. data/lib/mongoid/contextual/atomic.rb +4 -3
  17. data/lib/mongoid/contextual/find_and_modify.rb +1 -1
  18. data/lib/mongoid/contextual/geo_near.rb +238 -0
  19. data/lib/mongoid/contextual/map_reduce.rb +12 -1
  20. data/lib/mongoid/contextual/memory.rb +36 -31
  21. data/lib/mongoid/contextual/mongo.rb +147 -91
  22. data/lib/mongoid/contextual/queryable.rb +25 -0
  23. data/lib/mongoid/copyable.rb +4 -1
  24. data/lib/mongoid/criteria.rb +23 -275
  25. data/lib/mongoid/criterion/findable.rb +179 -0
  26. data/lib/mongoid/criterion/modifiable.rb +191 -0
  27. data/lib/mongoid/criterion/scoping.rb +11 -6
  28. data/lib/mongoid/document.rb +7 -56
  29. data/lib/mongoid/equality.rb +66 -0
  30. data/lib/mongoid/errors/mongoid_error.rb +7 -3
  31. data/lib/mongoid/extensions/array.rb +13 -1
  32. data/lib/mongoid/extensions/date.rb +9 -2
  33. data/lib/mongoid/extensions/hash.rb +38 -2
  34. data/lib/mongoid/extensions/nil_class.rb +12 -0
  35. data/lib/mongoid/extensions/object.rb +24 -0
  36. data/lib/mongoid/extensions/string.rb +14 -2
  37. data/lib/mongoid/extensions/time.rb +4 -1
  38. data/lib/mongoid/fields.rb +49 -5
  39. data/lib/mongoid/fields/foreign_key.rb +12 -0
  40. data/lib/mongoid/fields/standard.rb +12 -0
  41. data/lib/mongoid/finders.rb +8 -0
  42. data/lib/mongoid/hierarchy.rb +19 -1
  43. data/lib/mongoid/indexes.rb +30 -4
  44. data/lib/mongoid/indexes/validators/options.rb +12 -2
  45. data/lib/mongoid/inspection.rb +2 -1
  46. data/lib/mongoid/matchers/strategies.rb +5 -5
  47. data/lib/mongoid/observer.rb +27 -36
  48. data/lib/mongoid/persistence.rb +42 -17
  49. data/lib/mongoid/persistence/atomic.rb +10 -5
  50. data/lib/mongoid/persistence/atomic/operation.rb +26 -9
  51. data/lib/mongoid/persistence/atomic/unset.rb +1 -1
  52. data/lib/mongoid/persistence/operations/embedded/insert.rb +5 -2
  53. data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -2
  54. data/lib/mongoid/persistence/operations/update.rb +7 -3
  55. data/lib/mongoid/railties/database.rake +12 -19
  56. data/lib/mongoid/relations.rb +2 -0
  57. data/lib/mongoid/relations/accessors.rb +30 -8
  58. data/lib/mongoid/relations/binding.rb +5 -1
  59. data/lib/mongoid/relations/bindings/referenced/in.rb +1 -1
  60. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +3 -3
  61. data/lib/mongoid/relations/counter_cache.rb +107 -0
  62. data/lib/mongoid/relations/embedded/batchable.rb +13 -4
  63. data/lib/mongoid/relations/embedded/many.rb +30 -1
  64. data/lib/mongoid/relations/macros.rb +2 -0
  65. data/lib/mongoid/relations/marshalable.rb +0 -1
  66. data/lib/mongoid/relations/metadata.rb +63 -11
  67. data/lib/mongoid/relations/options.rb +1 -0
  68. data/lib/mongoid/relations/proxy.rb +45 -2
  69. data/lib/mongoid/relations/referenced/in.rb +11 -2
  70. data/lib/mongoid/relations/referenced/many.rb +31 -3
  71. data/lib/mongoid/relations/referenced/many_to_many.rb +31 -3
  72. data/lib/mongoid/relations/referenced/one.rb +1 -1
  73. data/lib/mongoid/relations/targets/enumerable.rb +5 -1
  74. data/lib/mongoid/relations/touchable.rb +35 -6
  75. data/lib/mongoid/reloading.rb +5 -3
  76. data/lib/mongoid/scoping.rb +2 -2
  77. data/lib/mongoid/sessions.rb +57 -7
  78. data/lib/mongoid/sessions/factory.rb +22 -1
  79. data/lib/mongoid/threaded.rb +4 -30
  80. data/lib/mongoid/threaded/lifecycle.rb +12 -12
  81. data/lib/mongoid/timestamps.rb +1 -0
  82. data/lib/mongoid/timestamps/created.rb +2 -0
  83. data/lib/mongoid/timestamps/created/short.rb +19 -0
  84. data/lib/mongoid/timestamps/short.rb +10 -0
  85. data/lib/mongoid/timestamps/updated.rb +2 -0
  86. data/lib/mongoid/timestamps/updated/short.rb +19 -0
  87. data/lib/mongoid/validations.rb +2 -0
  88. data/lib/mongoid/validations/queryable.rb +2 -2
  89. data/lib/mongoid/validations/uniqueness.rb +1 -18
  90. data/lib/mongoid/version.rb +1 -1
  91. data/lib/rails/generators/mongoid/model/model_generator.rb +1 -0
  92. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +3 -0
  93. data/lib/rails/mongoid.rb +53 -29
  94. data/lib/support/ruby_version.rb +26 -0
  95. metadata +18 -7
@@ -4,11 +4,6 @@ module Mongoid
4
4
  module Touchable
5
5
  extend ActiveSupport::Concern
6
6
 
7
- included do
8
- class_attribute :touchables
9
- self.touchables = []
10
- end
11
-
12
7
  module ClassMethods
13
8
 
14
9
  # Add the metadata to the touchable relations if the touch option was
@@ -23,9 +18,43 @@ module Mongoid
23
18
  #
24
19
  # @since 3.0.0
25
20
  def touchable(metadata)
26
- self.touchables.push(metadata.name) if metadata.touchable?
21
+ if metadata.touchable?
22
+ name = metadata.name
23
+ method_name = define_relation_touch_method(name)
24
+ after_create method_name
25
+ after_destroy method_name
26
+ after_touch method_name
27
+ end
27
28
  self
28
29
  end
30
+
31
+ private
32
+
33
+ # Define the method that will get called for touching belongs_to
34
+ # relations.
35
+ #
36
+ # @api private
37
+ #
38
+ # @example Define the touch relation.
39
+ # Model.define_relation_touch_method(:band)
40
+ #
41
+ # @param [ Symbol ] name The name of the relation.
42
+ #
43
+ # @since 3.1.0
44
+ #
45
+ # @return [ Symbol ] The method name.
46
+ def define_relation_touch_method(name)
47
+ method_name = "touch_#{name}_after_create_or_destroy"
48
+ class_eval <<-TOUCH
49
+ def #{method_name}
50
+ without_autobuild do
51
+ relation = __send__(:#{name})
52
+ relation.touch if relation
53
+ end
54
+ end
55
+ TOUCH
56
+ method_name.to_sym
57
+ end
29
58
  end
30
59
  end
31
60
  end
@@ -21,11 +21,13 @@ module Mongoid
21
21
  raise Errors::DocumentNotFound.new(self.class, id, id)
22
22
  end
23
23
  @attributes = reloaded
24
+ @attributes_before_type_cast = {}
24
25
  changed_attributes.clear
25
26
  apply_defaults
26
27
  reload_relations
27
28
  IdentityMap.set(self)
28
- run_callbacks(:initialize)
29
+ run_callbacks(:find) unless _find_callbacks.empty?
30
+ run_callbacks(:initialize) unless _initialize_callbacks.empty?
29
31
  self
30
32
  end
31
33
 
@@ -53,7 +55,7 @@ module Mongoid
53
55
  #
54
56
  # @since 2.3.2
55
57
  def reload_root_document
56
- {}.merge(collection.find(_id: id).one || {})
58
+ {}.merge(with(consistency: :strong).collection.find(_id: id).one || {})
57
59
  end
58
60
 
59
61
  # Reload the embedded document.
@@ -66,7 +68,7 @@ module Mongoid
66
68
  # @since 2.3.2
67
69
  def reload_embedded_document
68
70
  extract_embedded_attributes({}.merge(
69
- _root.collection.find(_id: _root.id).one
71
+ _root.with(consistency: :strong).collection.find(_id: _root.id).one
70
72
  ))
71
73
  end
72
74
 
@@ -204,10 +204,10 @@ module Mongoid
204
204
  #
205
205
  # @since 3.0.0
206
206
  def without_default_scope
207
- Threaded.begin("without_default_scope")
207
+ Threaded.begin_execution("without_default_scope")
208
208
  yield
209
209
  ensure
210
- Threaded.exit("without_default_scope")
210
+ Threaded.exit_execution("without_default_scope")
211
211
  end
212
212
 
213
213
  private
@@ -109,6 +109,20 @@ module Mongoid
109
109
  Threaded.sessions[:default] ||= Sessions::Factory.default
110
110
  end
111
111
 
112
+ # Disconnect all active sessions.
113
+ #
114
+ # @example Disconnect all active sessions.
115
+ # Mongoid::Sessions.disconnect
116
+ #
117
+ # @return [ true ] True.
118
+ #
119
+ # @since 3.1.0
120
+ def disconnect
121
+ Threaded.sessions.values.each do |session|
122
+ session.disconnect
123
+ end
124
+ end
125
+
112
126
  # Get a session with the provided name.
113
127
  #
114
128
  # @example Get a session with the name.
@@ -211,7 +225,7 @@ module Mongoid
211
225
  # @since 3.0.0
212
226
  def mongo_session
213
227
  session = __session__
214
- session.use(database_override || database_name)
228
+ session.use(database_override || current_database_name(session))
215
229
  session
216
230
  end
217
231
 
@@ -323,7 +337,7 @@ module Mongoid
323
337
  # @since 3.0.0
324
338
  def __collection_name__
325
339
  if storage_options && name = storage_options[:collection]
326
- name.to_sym
340
+ __evaluate__(name)
327
341
  else
328
342
  default_collection_name
329
343
  end
@@ -339,7 +353,7 @@ module Mongoid
339
353
  # @since 3.0.0
340
354
  def __database_name__
341
355
  if storage_options && name = storage_options[:database]
342
- name.to_sym
356
+ __evaluate__(name)
343
357
  else
344
358
  Mongoid.sessions[__session_name__][:database]
345
359
  end
@@ -355,7 +369,7 @@ module Mongoid
355
369
  # @since 3.0.0
356
370
  def __session_name__
357
371
  if storage_options && name = storage_options[:session]
358
- name.to_sym
372
+ __evaluate__(name)
359
373
  else
360
374
  :default
361
375
  end
@@ -372,10 +386,46 @@ module Mongoid
372
386
  def __session__
373
387
  if !(name = session_override).nil?
374
388
  Sessions.with_name(name)
375
- elsif storage_options && name = storage_options[:session]
376
- Sessions.with_name(name)
377
389
  else
378
- Sessions.default
390
+ Sessions.with_name(__session_name__)
391
+ end
392
+ end
393
+
394
+ # Eval the provided value, either byt calling it if it responds to call
395
+ # or returning the value itself.
396
+ #
397
+ # @api private
398
+ #
399
+ # @example Evaluate the name.
400
+ # Model.__evaluate__(:name)
401
+ #
402
+ # @param [ String, Symbol, Proc ] name The name.
403
+ #
404
+ # @return [ Symbol ] The value as a symbol.
405
+ #
406
+ # @since 3.1.0
407
+ def __evaluate__(name)
408
+ name.respond_to?(:call) ? name.call.to_sym : name.to_sym
409
+ end
410
+
411
+ # Get the name of the current database to use. Will check for a session
412
+ # override with a database first, then database name.
413
+ #
414
+ # @api private
415
+ #
416
+ # @example Get the current database name.
417
+ # Model.current_database_name
418
+ #
419
+ # @param [ Moped::Session ] session The current session.
420
+ #
421
+ # @return [ Symbol ] The current database name.
422
+ #
423
+ # @since 3.1.0
424
+ def current_database_name(session)
425
+ if session_override && name = session.options[:database]
426
+ name
427
+ else
428
+ database_name
379
429
  end
380
430
  end
381
431
  end
@@ -100,9 +100,30 @@ module Mongoid
100
100
  # @since 3.0.0
101
101
  def parse(config)
102
102
  options = config[:options].try(:dup) || {}
103
- parsed = config.has_key?(:uri) ? MongoUri.new(config[:uri]).to_hash : config
103
+ parsed = if config.has_key?(:uri)
104
+ MongoUri.new(config[:uri]).to_hash
105
+ else
106
+ inject_ports(config)
107
+ end
104
108
  [ parsed, options.symbolize_keys ]
105
109
  end
110
+
111
+ # Will inject the default port of 27017 if not supplied.
112
+ #
113
+ # @example Inject default ports.
114
+ # factory.inject_ports(config)
115
+ #
116
+ # @param [ Hash ] config The session configuration.
117
+ #
118
+ # @return [ Hash ] The altered configuration.
119
+ #
120
+ # @since 3.1.0
121
+ def inject_ports(config)
122
+ config["hosts"] = config["hosts"].map do |host|
123
+ host =~ /:/ ? host : "#{host}:27017"
124
+ end
125
+ config
126
+ end
106
127
  end
107
128
  end
108
129
  end
@@ -11,14 +11,14 @@ module Mongoid
11
11
  # Begin entry into a named thread local stack.
12
12
  #
13
13
  # @example Begin entry into the stack.
14
- # Threaded.begin(:create)
14
+ # Threaded.begin_execution(:create)
15
15
  #
16
16
  # @param [ String ] name The name of the stack
17
17
  #
18
18
  # @return [ true ] True.
19
19
  #
20
20
  # @since 2.4.0
21
- def begin(name)
21
+ def begin_execution(name)
22
22
  stack(name).push(true)
23
23
  end
24
24
 
@@ -77,14 +77,14 @@ module Mongoid
77
77
  # Exit from a named thread local stack.
78
78
  #
79
79
  # @example Exit from the stack.
80
- # Threaded.exit(:create)
80
+ # Threaded.exit_execution(:create)
81
81
  #
82
82
  # @param [ Symbol ] name The name of the stack
83
83
  #
84
84
  # @return [ true ] True.
85
85
  #
86
86
  # @since 2.4.0
87
- def exit(name)
87
+ def exit_execution(name)
88
88
  stack(name).pop
89
89
  end
90
90
 
@@ -241,32 +241,6 @@ module Mongoid
241
241
  end
242
242
  end
243
243
 
244
- # Get the insert consumer from the current thread.
245
- #
246
- # @example Get the insert consumer.
247
- # Threaded.insert
248
- #
249
- # @return [ Object ] The batch insert consumer.
250
- #
251
- # @since 2.1.0
252
- def insert(name)
253
- Thread.current["[mongoid][#{name}]:insert-consumer"]
254
- end
255
-
256
- # Set the insert consumer on the current thread.
257
- #
258
- # @example Set the insert consumer.
259
- # Threaded.insert = consumer
260
- #
261
- # @param [ Object ] consumer The insert consumer.
262
- #
263
- # @return [ Object ] The insert consumer.
264
- #
265
- # @since 2.1.0
266
- def set_insert(name, consumer)
267
- Thread.current["[mongoid][#{name}]:insert-consumer"] = consumer
268
- end
269
-
270
244
  # Get the persistence options for the current thread.
271
245
  #
272
246
  # @example Get the persistence options.
@@ -22,10 +22,10 @@ module Mongoid
22
22
  #
23
23
  # @since 2.2.0
24
24
  def _assigning
25
- Threaded.begin("assign")
25
+ Threaded.begin_execution("assign")
26
26
  yield
27
27
  ensure
28
- Threaded.exit("assign")
28
+ Threaded.exit_execution("assign")
29
29
  end
30
30
 
31
31
  # Is the current thread in assigning mode?
@@ -51,10 +51,10 @@ module Mongoid
51
51
  #
52
52
  # @since 2.1.0
53
53
  def _binding
54
- Threaded.begin("bind")
54
+ Threaded.begin_execution("bind")
55
55
  yield
56
56
  ensure
57
- Threaded.exit("bind")
57
+ Threaded.exit_execution("bind")
58
58
  end
59
59
 
60
60
  # Is the current thread in binding mode?
@@ -80,10 +80,10 @@ module Mongoid
80
80
  #
81
81
  # @since 2.1.0
82
82
  def _building
83
- Threaded.begin("build")
83
+ Threaded.begin_execution("build")
84
84
  yield
85
85
  ensure
86
- Threaded.exit("build")
86
+ Threaded.exit_execution("build")
87
87
  end
88
88
 
89
89
  # Is the current thread in building mode?
@@ -121,10 +121,10 @@ module Mongoid
121
121
  #
122
122
  # @since 2.3.2
123
123
  def _loading
124
- Threaded.begin("load")
124
+ Threaded.begin_execution("load")
125
125
  yield
126
126
  ensure
127
- Threaded.exit("load")
127
+ Threaded.exit_execution("load")
128
128
  end
129
129
 
130
130
  # Is the current thread in loading mode?
@@ -150,10 +150,10 @@ module Mongoid
150
150
  #
151
151
  # @since 2.3.4
152
152
  def _loading_revision
153
- Threaded.begin("load_revision")
153
+ Threaded.begin_execution("load_revision")
154
154
  yield
155
155
  ensure
156
- Threaded.exit("load_revision")
156
+ Threaded.exit_execution("load_revision")
157
157
  end
158
158
 
159
159
  module ClassMethods
@@ -169,10 +169,10 @@ module Mongoid
169
169
  #
170
170
  # @since 2.1.0
171
171
  def _creating
172
- Threaded.begin("create")
172
+ Threaded.begin_execution("create")
173
173
  yield
174
174
  ensure
175
- Threaded.exit("create")
175
+ Threaded.exit_execution("create")
176
176
  end
177
177
 
178
178
  # Is the current thread in loading revision mode?
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/timestamps/created"
3
3
  require "mongoid/timestamps/updated"
4
+ require "mongoid/timestamps/short"
4
5
  require "mongoid/timestamps/timeless"
5
6
 
6
7
  module Mongoid
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ require "mongoid/timestamps/created/short"
3
+
2
4
  module Mongoid
3
5
  module Timestamps
4
6
  # This module handles the behaviour for setting up document created at
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Timestamps
4
+ module Created
5
+
6
+ # Adds a created_at timestamp to the document, but it is stored as c_at
7
+ # with a created_at alias.
8
+ module Short
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Created
13
+ fields.delete("created_at")
14
+ field :c_at, type: Time, as: :created_at
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Timestamps
4
+ module Short
5
+ extend ActiveSupport::Concern
6
+ include Created::Short
7
+ include Updated::Short
8
+ end
9
+ end
10
+ end
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ require "mongoid/timestamps/updated/short"
3
+
2
4
  module Mongoid
3
5
  module Timestamps
4
6
  # This module handles the behaviour for setting up document updated at
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Timestamps
4
+ module Updated
5
+
6
+ # Adds a created_at timestamp to the document, but it is stored as c_at
7
+ # with a created_at alias.
8
+ module Short
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Updated
13
+ fields.delete("updated_at")
14
+ field :u_at, type: Time, as: :updated_at
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end