mongoid 2.3.1 → 2.3.2

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