mongoid 2.3.1 → 2.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 (47) hide show
  1. data/CHANGELOG.md +34 -1
  2. data/lib/mongoid.rb +3 -2
  3. data/lib/mongoid/atomic.rb +23 -2
  4. data/lib/mongoid/attributes.rb +0 -21
  5. data/lib/mongoid/callbacks.rb +9 -1
  6. data/lib/mongoid/components.rb +2 -0
  7. data/lib/mongoid/config.rb +4 -2
  8. data/lib/mongoid/contexts/mongo.rb +19 -8
  9. data/lib/mongoid/criterion/inclusion.rb +6 -4
  10. data/lib/mongoid/dirty.rb +1 -0
  11. data/lib/mongoid/document.rb +1 -25
  12. data/lib/mongoid/extensions/hash/criteria_helpers.rb +13 -0
  13. data/lib/mongoid/extensions/object/yoda.rb +1 -0
  14. data/lib/mongoid/matchers/strategies.rb +6 -1
  15. data/lib/mongoid/persistence.rb +2 -21
  16. data/lib/mongoid/railtie.rb +8 -1
  17. data/lib/mongoid/relations/accessors.rb +7 -5
  18. data/lib/mongoid/relations/binding.rb +2 -29
  19. data/lib/mongoid/relations/bindings/embedded/in.rb +4 -4
  20. data/lib/mongoid/relations/bindings/embedded/many.rb +4 -4
  21. data/lib/mongoid/relations/bindings/embedded/one.rb +4 -4
  22. data/lib/mongoid/relations/bindings/referenced/in.rb +4 -4
  23. data/lib/mongoid/relations/bindings/referenced/many.rb +4 -4
  24. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
  25. data/lib/mongoid/relations/bindings/referenced/one.rb +4 -4
  26. data/lib/mongoid/relations/builder.rb +18 -4
  27. data/lib/mongoid/relations/builders.rb +0 -17
  28. data/lib/mongoid/relations/builders/embedded/in.rb +3 -3
  29. data/lib/mongoid/relations/builders/embedded/many.rb +4 -4
  30. data/lib/mongoid/relations/builders/embedded/one.rb +3 -3
  31. data/lib/mongoid/relations/builders/nested_attributes/many.rb +1 -1
  32. data/lib/mongoid/relations/builders/referenced/one.rb +1 -0
  33. data/lib/mongoid/relations/embedded/in.rb +4 -3
  34. data/lib/mongoid/relations/embedded/many.rb +6 -5
  35. data/lib/mongoid/relations/embedded/one.rb +4 -3
  36. data/lib/mongoid/relations/metadata.rb +20 -5
  37. data/lib/mongoid/relations/proxy.rb +1 -48
  38. data/lib/mongoid/relations/referenced/in.rb +4 -3
  39. data/lib/mongoid/relations/referenced/many.rb +4 -3
  40. data/lib/mongoid/relations/referenced/many_to_many.rb +5 -4
  41. data/lib/mongoid/relations/referenced/one.rb +4 -3
  42. data/lib/mongoid/reloading.rb +91 -0
  43. data/lib/mongoid/state.rb +15 -22
  44. data/lib/mongoid/threaded.rb +51 -0
  45. data/lib/mongoid/threaded/lifecycle.rb +163 -0
  46. data/lib/mongoid/version.rb +1 -1
  47. metadata +21 -19
@@ -26,8 +26,8 @@ module Mongoid # :nodoc:
26
26
  def bind
27
27
  base.metadata = metadata.inverse_metadata(target)
28
28
  base.parentize(target)
29
- unless binding?
30
- binding do
29
+ unless _binding?
30
+ _binding do
31
31
  if base.embedded_many?
32
32
  target.do_or_do_not(metadata.inverse(target)).push(base)
33
33
  else
@@ -51,8 +51,8 @@ module Mongoid # :nodoc:
51
51
  #
52
52
  # @since 2.0.0.rc.1
53
53
  def unbind
54
- unless binding?
55
- binding do
54
+ unless _binding?
55
+ _binding do
56
56
  if base.embedded_many?
57
57
  target.do_or_do_not(metadata.inverse(target)).delete(base)
58
58
  else
@@ -42,8 +42,8 @@ module Mongoid # :nodoc:
42
42
  # @since 2.0.0.rc.1
43
43
  def bind_one(doc)
44
44
  doc.parentize(base)
45
- unless binding?
46
- binding do
45
+ unless _binding?
46
+ _binding do
47
47
  unless metadata.versioned?
48
48
  doc.do_or_do_not(metadata.inverse_setter(target), base)
49
49
  end
@@ -80,8 +80,8 @@ module Mongoid # :nodoc:
80
80
  #
81
81
  # @since 2.0.0.rc.1
82
82
  def unbind_one(doc)
83
- unless binding?
84
- binding do
83
+ unless _binding?
84
+ _binding do
85
85
  doc.do_or_do_not(metadata.inverse_setter(target), nil)
86
86
  end
87
87
  end
@@ -25,8 +25,8 @@ module Mongoid # :nodoc:
25
25
  # @since 2.0.0.rc.1
26
26
  def bind
27
27
  target.parentize(base)
28
- unless binding?
29
- binding do
28
+ unless _binding?
29
+ _binding do
30
30
  target.do_or_do_not(metadata.inverse_setter(target), base)
31
31
  end
32
32
  end
@@ -47,8 +47,8 @@ module Mongoid # :nodoc:
47
47
  #
48
48
  # @since 2.0.0.rc.1
49
49
  def unbind
50
- unless binding?
51
- binding do
50
+ unless _binding?
51
+ _binding do
52
52
  target.do_or_do_not(metadata.inverse_setter(target), nil)
53
53
  end
54
54
  end
@@ -19,8 +19,8 @@ module Mongoid # :nodoc:
19
19
  #
20
20
  # @since 2.0.0.rc.1
21
21
  def bind
22
- unless binding?
23
- binding do
22
+ unless _binding?
23
+ _binding do
24
24
  inverse = metadata.inverse(target)
25
25
  base.you_must(metadata.foreign_key_setter, target.id)
26
26
  if metadata.inverse_type
@@ -51,8 +51,8 @@ module Mongoid # :nodoc:
51
51
  #
52
52
  # @since 2.0.0.rc.1
53
53
  def unbind
54
- unless binding?
55
- binding do
54
+ unless _binding?
55
+ _binding do
56
56
  inverse = metadata.inverse(target)
57
57
  base.you_must(metadata.foreign_key_setter, nil)
58
58
  if metadata.inverse_type
@@ -17,8 +17,8 @@ module Mongoid # :nodoc:
17
17
  #
18
18
  # @since 2.0.0.rc.1
19
19
  def bind_one(doc)
20
- unless binding?
21
- binding do
20
+ unless _binding?
21
+ _binding do
22
22
  doc.you_must(metadata.foreign_key_setter, base.id)
23
23
  if metadata.type
24
24
  doc.you_must(metadata.type_setter, base.class.model_name)
@@ -37,8 +37,8 @@ module Mongoid # :nodoc:
37
37
  #
38
38
  # @since 2.0.0.rc.1
39
39
  def unbind_one(doc)
40
- unless binding?
41
- binding do
40
+ unless _binding?
41
+ _binding do
42
42
  doc.you_must(metadata.foreign_key_setter, nil)
43
43
  if metadata.type
44
44
  doc.you_must(metadata.type_setter, nil)
@@ -17,8 +17,8 @@ module Mongoid # :nodoc:
17
17
  #
18
18
  # @since 2.0.0.rc.1
19
19
  def bind_one(doc)
20
- unless binding?
21
- binding do
20
+ unless _binding?
21
+ _binding do
22
22
  inverse_keys = doc.you_must(metadata.inverse_foreign_key)
23
23
  inverse_keys.push(base.id) if inverse_keys
24
24
  base.synced[metadata.foreign_key] = true
@@ -34,8 +34,8 @@ module Mongoid # :nodoc:
34
34
  #
35
35
  # @since 2.0.0.rc.1
36
36
  def unbind_one(doc)
37
- unless binding?
38
- binding do
37
+ unless _binding?
38
+ _binding do
39
39
  base.send(metadata.foreign_key).delete_one(doc.id)
40
40
  inverse_keys = doc.you_must(metadata.inverse_foreign_key)
41
41
  inverse_keys.delete_one(base.id) if inverse_keys
@@ -19,8 +19,8 @@ module Mongoid # :nodoc:
19
19
  #
20
20
  # @since 2.0.0.rc.1
21
21
  def bind
22
- unless binding?
23
- binding do
22
+ unless _binding?
23
+ _binding do
24
24
  target.you_must(metadata.foreign_key_setter, base.id)
25
25
  target.send(metadata.inverse_setter, base)
26
26
  if metadata.type
@@ -40,8 +40,8 @@ module Mongoid # :nodoc:
40
40
  #
41
41
  # @since 2.0.0.rc.1
42
42
  def unbind
43
- unless binding?
44
- binding do
43
+ unless _binding?
44
+ _binding do
45
45
  target.you_must(metadata.foreign_key_setter, nil)
46
46
  target.send(metadata.inverse_setter, nil)
47
47
  if metadata.type
@@ -6,25 +6,39 @@ module Mongoid # :nodoc:
6
6
  # looking up a relation's target from the database, or creating them from a
7
7
  # supplied attributes hash.
8
8
  class Builder
9
+ include Threaded::Lifecycle
9
10
 
10
- attr_reader :metadata, :object, :loading
11
+ attr_reader :base, :metadata, :object
11
12
 
12
13
  # Instantiate the new builder for a relation.
13
14
  #
14
15
  # @example Create the builder.
15
16
  # Builder.new(metadata, { :field => "value })
16
17
  #
18
+ # @param [ Document ] base The base document.
17
19
  # @param [ Metdata ] metadata The metadata for the relation.
18
20
  # @param [ Hash, BSON::ObjectId ] object The attributes to build from or
19
21
  # id to query with.
20
22
  #
21
23
  # @since 2.0.0.rc.1
22
- def initialize(metadata, object, loading = false)
23
- @metadata, @object = metadata, object
24
- @loading = loading
24
+ def initialize(base, metadata, object)
25
+ @base, @metadata, @object = base, metadata, object
25
26
  end
26
27
 
27
28
  protected
29
+
30
+ # Get the class from the metadata.
31
+ #
32
+ # @example Get the class.
33
+ # builder.klass
34
+ #
35
+ # @return [ Class ] The class from the metadata.
36
+ #
37
+ # @since 2.3.2
38
+ def klass
39
+ @klass ||= metadata.klass
40
+ end
41
+
28
42
  # Do we need to perform a database query? It will be so if the object we
29
43
  # have is not a document.
30
44
  #
@@ -32,23 +32,6 @@ module Mongoid # :nodoc:
32
32
  module Builders
33
33
  extend ActiveSupport::Concern
34
34
 
35
- # Execute a block in building mode.
36
- #
37
- # @example Execute in building mode.
38
- # _building do
39
- # relation.push(doc)
40
- # end
41
- #
42
- # @return [ Object ] The return value of the block.
43
- #
44
- # @since 2.1.0
45
- def _building
46
- Threaded.begin_build
47
- yield
48
- ensure
49
- Threaded.exit_build
50
- end
51
-
52
35
  module ClassMethods #:nodoc:
53
36
 
54
37
  # Defines a builder method for an embeds_one relation. This is
@@ -16,10 +16,10 @@ module Mongoid # :nodoc:
16
16
  # @return [ Document ] A single document.
17
17
  def build(type = nil)
18
18
  return object unless object.is_a?(Hash)
19
- if loading
20
- Mongoid::Factory.from_db(metadata.klass, object)
19
+ if _loading?
20
+ Factory.from_db(klass, object)
21
21
  else
22
- Mongoid::Factory.build(metadata.klass, object)
22
+ Factory.build(klass, object)
23
23
  end
24
24
  end
25
25
  end
@@ -1,5 +1,4 @@
1
1
  # encoding: utf-8
2
-
3
2
  require "mongoid/relations/embedded/sort"
4
3
 
5
4
  module Mongoid # :nodoc:
@@ -8,6 +7,7 @@ module Mongoid # :nodoc:
8
7
  module Embedded #:nodoc:
9
8
  class Many < Builder #:nodoc:
10
9
  include Relations::Embedded::Sort
10
+
11
11
  # Builds the document out of the attributes using the provided
12
12
  # metadata on the relation. Instantiates through the factory in order
13
13
  # to make sure subclasses and allocation are used if fitting. This
@@ -24,10 +24,10 @@ module Mongoid # :nodoc:
24
24
  return object if object.first.is_a?(Document)
25
25
  [].tap do |docs|
26
26
  object.each do |attrs|
27
- if loading
28
- docs << Mongoid::Factory.from_db(metadata.klass, attrs)
27
+ if _loading?
28
+ docs << Factory.from_db(klass, attrs)
29
29
  else
30
- docs << Mongoid::Factory.build(metadata.klass, attrs)
30
+ docs << Factory.build(klass, attrs)
31
31
  end
32
32
  end
33
33
  sort_documents!(docs, metadata) if metadata.order
@@ -17,10 +17,10 @@ module Mongoid # :nodoc:
17
17
  # @return [ Document ] A single document.
18
18
  def build(type = nil)
19
19
  return object unless object.is_a?(Hash)
20
- if loading
21
- Mongoid::Factory.from_db(metadata.klass, object)
20
+ if _loading?
21
+ Factory.from_db(klass, object)
22
22
  else
23
- Mongoid::Factory.build(metadata.klass, object)
23
+ Factory.build(klass, object)
24
24
  end
25
25
  end
26
26
  end
@@ -91,7 +91,7 @@ module Mongoid # :nodoc:
91
91
  # @param [ Hash ] attrs The single document attributes to process.
92
92
  def process(parent, attrs)
93
93
  return if reject?(parent, attrs)
94
- if id = attrs["id"] || attrs["_id"]
94
+ if id = attrs.extract_id
95
95
  doc = existing.find(convert_id(id))
96
96
  if destroyable?(attrs)
97
97
  existing.delete(doc)
@@ -16,6 +16,7 @@ module Mongoid # :nodoc:
16
16
  # @return [ Document ] A single document.
17
17
  def build(type = nil)
18
18
  return object unless query?
19
+ return nil if base.new_record?
19
20
  metadata.criteria(Conversions.flag(object, metadata)).from_map_or_db
20
21
  end
21
22
  end
@@ -89,7 +89,7 @@ module Mongoid # :nodoc:
89
89
  #
90
90
  # @since 2.1.0
91
91
  def persistable?
92
- target.persisted? && !binding? && !_building?
92
+ target.persisted? && !_binding? && !_building?
93
93
  end
94
94
 
95
95
  class << self
@@ -100,14 +100,15 @@ module Mongoid # :nodoc:
100
100
  # @example Get the builder.
101
101
  # Embedded::In.builder(meta, object, person)
102
102
  #
103
+ # @param [ Document ] base The base document.
103
104
  # @param [ Metadata ] meta The metadata of the relation.
104
105
  # @param [ Document, Hash ] object A document or attributes to build with.
105
106
  #
106
107
  # @return [ Builder ] A newly instantiated builder object.
107
108
  #
108
109
  # @since 2.0.0.rc.1
109
- def builder(meta, object, loading = false)
110
- Builders::Embedded::In.new(meta, object, loading)
110
+ def builder(base, meta, object)
111
+ Builders::Embedded::In.new(base, meta, object)
111
112
  end
112
113
 
113
114
  # Returns true if the relation is an embedded one. In this case
@@ -145,7 +145,7 @@ module Mongoid # :nodoc:
145
145
  # @since 2.0.0.rc.1
146
146
  def delete(document)
147
147
  target.delete_one(document).tap do |doc|
148
- if doc && !binding?
148
+ if doc && !_binding?
149
149
  if _assigning?
150
150
  base.add_atomic_pull(doc)
151
151
  else
@@ -261,7 +261,7 @@ module Mongoid # :nodoc:
261
261
  else
262
262
  atomically(:$set) do
263
263
  if replacement.first.is_a?(Hash)
264
- replacement = Many.builder(metadata, replacement).build
264
+ replacement = Many.builder(base, metadata, replacement).build
265
265
  end
266
266
  proxy.target = replacement.compact
267
267
  if _assigning?
@@ -390,7 +390,7 @@ module Mongoid # :nodoc:
390
390
  #
391
391
  # @since 2.1.0
392
392
  def persistable?
393
- base.persisted? && !binding?
393
+ base.persisted? && !_binding?
394
394
  end
395
395
 
396
396
  # Reindex all the target elements. This is useful when performing
@@ -437,6 +437,7 @@ module Mongoid # :nodoc:
437
437
  # @example Get the builder.
438
438
  # Embedded::Many.builder(meta, object)
439
439
  #
440
+ # @param [ Document ] base The base document.
440
441
  # @param [ Metadata ] meta The metadata of the relation.
441
442
  # @param [ Document, Hash ] object A document or attributes to build
442
443
  # with.
@@ -444,8 +445,8 @@ module Mongoid # :nodoc:
444
445
  # @return [ Builder ] A newly instantiated builder object.
445
446
  #
446
447
  # @since 2.0.0.rc.1
447
- def builder(meta, object, loading = false)
448
- Builders::Embedded::Many.new(meta, object, loading)
448
+ def builder(base, meta, object)
449
+ Builders::Embedded::Many.new(base, meta, object)
449
450
  end
450
451
 
451
452
  # Returns true if the relation is an embedded one. In this case
@@ -73,7 +73,7 @@ module Mongoid # :nodoc:
73
73
  #
74
74
  # @since 2.1.0
75
75
  def persistable?
76
- base.persisted? && !binding? && !_building? && !_assigning?
76
+ base.persisted? && !_binding? && !_building? && !_assigning?
77
77
  end
78
78
 
79
79
  class << self
@@ -84,14 +84,15 @@ module Mongoid # :nodoc:
84
84
  # @example Get the builder.
85
85
  # Embedded::One.builder(meta, object, person)
86
86
  #
87
+ # @param [ Document ] base The base document.
87
88
  # @param [ Metadata ] meta The metadata of the relation.
88
89
  # @param [ Document, Hash ] object A document or attributes to build with.
89
90
  #
90
91
  # @return [ Builder ] A newly instantiated builder object.
91
92
  #
92
93
  # @since 2.0.0.rc.1
93
- def builder(meta, object, loading = false)
94
- Builders::Embedded::One.new(meta, object, loading)
94
+ def builder(base, meta, object)
95
+ Builders::Embedded::One.new(base, meta, object)
95
96
  end
96
97
 
97
98
  # Returns true if the relation is an embedded one. In this case
@@ -62,13 +62,14 @@ module Mongoid # :nodoc:
62
62
  # @example Get the builder.
63
63
  # metadata.builder(document)
64
64
  #
65
+ # @param [ Document ] base The base document.
65
66
  # @param [ Object ] object A document or attributes to give the builder.
66
67
  #
67
68
  # @return [ Builder ] The builder for the relation.
68
69
  #
69
70
  # @since 2.0.0.rc.1
70
- def builder(object, loading = false)
71
- relation.builder(self, object, loading)
71
+ def builder(base, object)
72
+ relation.builder(base, self, object)
72
73
  end
73
74
 
74
75
  # Returns the name of the strategy used for handling dependent relations.
@@ -401,9 +402,7 @@ module Mongoid # :nodoc:
401
402
  #
402
403
  # @since 2.0.0.rc.1
403
404
  def inverse_foreign_key
404
- @inverse_foreign_key ||=
405
- ( inverse_of ? inverse_of.to_s.singularize : inverse_class_name.demodulize.underscore ) <<
406
- relation.foreign_key_suffix
405
+ @inverse_foreign_key ||= determine_inverse_foreign_key
407
406
  end
408
407
 
409
408
  # Returns the inverse class of the proxied relation.
@@ -809,6 +808,22 @@ module Mongoid # :nodoc:
809
808
  end
810
809
  end
811
810
 
811
+ # Determine the inverse foreign key of the relation.
812
+ #
813
+ # @example Determine the inverse foreign key.
814
+ # metadata.determine_inverse_foreign_key
815
+ #
816
+ # @return [ String ] The inverse.
817
+ #
818
+ # @since 2.3.2
819
+ def determine_inverse_foreign_key
820
+ if has_key?(:inverse_of)
821
+ inverse_of ? "#{inverse_of.to_s.singularize}#{relation.foreign_key_suffix}" : nil
822
+ else
823
+ "#{inverse_class_name.demodulize.underscore}#{relation.foreign_key_suffix}"
824
+ end
825
+ end
826
+
812
827
  # Determine the inverse relation. Memoizing #inverse_relation and adding
813
828
  # this method dropped 5 seconds off the test suite as a performance
814
829
  # improvement.