Skip to content
This repository
Browse code

Fix multi-level hash update w/o nested attributes. Fixes #1936.

  • Loading branch information...
commit dec16ac7bb72b4aeadbe5ba9100a47dc835b3135 1 parent 8797e28
Durran Jordan authored May 05, 2012
4  CHANGELOG.md
Source Rendered
@@ -7,6 +7,10 @@ For instructions on upgrading to newer versions, visit
7 7
 
8 8
 ### Resolved Issues
9 9
 
  10
+* \#1936 Allow setting n levels deep embedded documents atomically without
  11
+  conflicting mods when not using nested attributes or documents themselves
  12
+  in an update call from the parent.
  13
+
10 14
 * \#1957/\#1954 Ensure database name is set with inheritance.
11 15
   (Hans Hasselberg)
12 16
 
3  lib/mongoid/atomic.rb
@@ -252,6 +252,9 @@ def delayed_atomic_pulls
252 252
     # @example Get the atomic paths.
253 253
     #   document.atomic_paths
254 254
     #
  255
+    # @todo: Durran: Should probably raise error for embedded docs w/o
  256
+    #   metadata.
  257
+    #
255 258
     # @return [ Object ] The associated path.
256 259
     #
257 260
     # @since 2.1.0
10  lib/mongoid/relations/embedded/many.rb
@@ -307,7 +307,11 @@ def substitute(replacement)
307 307
               atomically(:$set) do
308 308
                 base.delayed_atomic_sets.clear
309 309
                 if replacement.first.is_a?(Hash)
310  
-                  replacement = Many.builder(base, metadata, replacement).build
  310
+                  replacement = replacement.map do |doc|
  311
+                    attributes = { metadata: metadata, _parent: base }
  312
+                    attributes.merge!(doc)
  313
+                    Factory.build(klass, attributes)
  314
+                  end
311 315
                 end
312 316
                 docs = replacement.compact
313 317
                 proxy.target = docs
@@ -319,6 +323,10 @@ def substitute(replacement)
319 323
                 end
320 324
                 if _assigning?
321 325
                   name = _unscoped.first.atomic_path
  326
+                  base._children.each do |child|
  327
+                    child.delayed_atomic_sets.clear
  328
+                  end
  329
+                  base.instance_variable_set(:@_children, nil)
322 330
                   base.delayed_atomic_sets[name] = proxy.as_document
323 331
                 end
324 332
               end
49  spec/functional/mongoid/relations/embedded/many_spec.rb
@@ -3025,4 +3025,53 @@
3025 3025
       end
3026 3026
     end
3027 3027
   end
  3028
+
  3029
+  context "when adding a document" do
  3030
+
  3031
+    let(:person) do
  3032
+      Person.new
  3033
+    end
  3034
+
  3035
+    let(:address_one) do
  3036
+      Address.new(street: "hobrecht")
  3037
+    end
  3038
+
  3039
+    let(:first_add) do
  3040
+      person.addresses.push(address_one)
  3041
+    end
  3042
+  end
  3043
+
  3044
+  context "when updating multiple levels in one update" do
  3045
+
  3046
+    let!(:person) do
  3047
+      Person.create(
  3048
+        addresses: [
  3049
+          { locations: [{ name: "home" }]}
  3050
+        ]
  3051
+      )
  3052
+    end
  3053
+
  3054
+    context "when updating with hashes" do
  3055
+
  3056
+      let(:from_db) do
  3057
+        Person.find(person.id)
  3058
+      end
  3059
+
  3060
+      before do
  3061
+        from_db.update_attributes(
  3062
+          addresses: [
  3063
+            { locations: [{ name: "work" }]}
  3064
+          ]
  3065
+        )
  3066
+      end
  3067
+
  3068
+      let(:updated) do
  3069
+        person.reload.addresses.first.locations.first
  3070
+      end
  3071
+
  3072
+      it "updates the nested document" do
  3073
+        updated.name.should eq("work")
  3074
+      end
  3075
+    end
  3076
+  end
3028 3077
 end

0 notes on commit dec16ac

Please sign in to comment.
Something went wrong with that request. Please try again.