Skip to content
This repository
Browse code

Fix ActiveModel::Errors#dup

Since ActiveModel::Errors instance keeps all error messages as hash
we should duplicate this object as well.

Previously ActiveModel::Errors was a subclass of ActiveSupport::OrderedHash,
which results in different behavior on dup, this may result in regression for
people relying on it.

Because Rails 3.2 stills supports Ruby 1.8.7 in order to properly fix this
regression we need to backport #initialize_dup.
  • Loading branch information...
commit 7021184f9cd385bc7f7c7bedf6ce871806b1981e 1 parent f9275e5
Paweł Kondzior authored
15  activemodel/lib/active_model/errors.rb
@@ -79,6 +79,19 @@ def initialize(base)
79 79
       @messages = ActiveSupport::OrderedHash.new
80 80
     end
81 81
 
  82
+    def initialize_dup(other)
  83
+      @messages = other.messages.dup
  84
+    end
  85
+
  86
+    # Backport dup from 1.9 so that #initialize_dup gets called
  87
+    unless Object.respond_to?(:initialize_dup)
  88
+      def dup # :nodoc:
  89
+        copy = super
  90
+        copy.initialize_dup(self)
  91
+        copy
  92
+      end
  93
+    end
  94
+
82 95
     # Clear the messages
83 96
     def clear
84 97
       messages.clear
@@ -119,7 +132,7 @@ def [](attribute)
119 132
     #   p.errors[:name] = "must be set"
120 133
     #   p.errors[:name] # => ['must be set']
121 134
     def []=(attribute, error)
122  
-      self[attribute.to_sym] << error
  135
+      self[attribute] << error
123 136
     end
124 137
 
125 138
     # Iterates through each error key, value pair in the error messages hash.
8  activemodel/test/cases/errors_test.rb
@@ -46,6 +46,14 @@ def test_has_key?
46 46
     assert errors.has_key?(:foo), 'errors should have key :foo'
47 47
   end
48 48
 
  49
+  def test_dup
  50
+    errors = ActiveModel::Errors.new(self)
  51
+    errors[:foo] = 'bar'
  52
+    errors_dup = errors.dup
  53
+    errors_dup[:bar] = 'omg'
  54
+    assert_not_same errors_dup.messages, errors.messages
  55
+  end
  56
+
49 57
   test "should return true if no errors" do
50 58
     person = Person.new
51 59
     person.errors[:foo]

0 notes on commit 7021184

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