mongoid 3.0.23 → 3.1.0

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