File tree Expand file tree Collapse file tree 3 files changed +50
-6
lines changed
activerecord/lib/active_record/relation Expand file tree Collapse file tree 3 files changed +50
-6
lines changed Original file line number Diff line number Diff line change @@ -53,7 +53,10 @@ def original_value
53
53
end
54
54
55
55
def value_for_database
56
- type . serialize ( value )
56
+ if !defined? ( @value_for_database ) || type . changed_in_place? ( @value_for_database , value )
57
+ @value_for_database = _value_for_database
58
+ end
59
+ @value_for_database
57
60
end
58
61
59
62
def serializable? ( &block )
@@ -159,6 +162,10 @@ def changed_from_assignment?
159
162
assigned? && type . changed? ( original_value , value , value_before_type_cast )
160
163
end
161
164
165
+ def _value_for_database
166
+ type . serialize ( value )
167
+ end
168
+
162
169
def _original_value_for_database
163
170
type . serialize ( original_value )
164
171
end
@@ -179,13 +186,14 @@ def type_cast(value)
179
186
type . cast ( value )
180
187
end
181
188
182
- def value_for_database
183
- Type ::SerializeCastValue . serialize ( type , value )
184
- end
185
-
186
189
def came_from_user?
187
190
!type . value_constructed_by_mass_assignment? ( value_before_type_cast )
188
191
end
192
+
193
+ private
194
+ def _value_for_database
195
+ Type ::SerializeCastValue . serialize ( type , value )
196
+ end
189
197
end
190
198
191
199
class WithCastValue < Attribute # :nodoc:
Original file line number Diff line number Diff line change 5
5
module ActiveModel
6
6
class AttributeTest < ActiveModel ::TestCase
7
7
class InscribingType
8
+ def changed_in_place? ( raw_old_value , new_value )
9
+ false
10
+ end
11
+
8
12
def cast ( value )
9
13
"cast(#{ value } )"
10
14
end
@@ -96,6 +100,37 @@ def serialize_cast_value(value)
96
100
assert_equal "serialize_cast_value(cast(whatever))" , attribute . value_for_database
97
101
end
98
102
103
+ test "value_for_database is memoized" do
104
+ count = 0
105
+ @type . define_singleton_method ( :serialize ) do |value |
106
+ count += 1
107
+ nil
108
+ end
109
+
110
+ attribute = Attribute . from_user ( nil , "whatever" , @type )
111
+
112
+ attribute . value_for_database
113
+ attribute . value_for_database
114
+ assert_equal 1 , count
115
+ end
116
+
117
+ test "value_for_database is recomputed when value changes in place" do
118
+ count = 0
119
+ @type . define_singleton_method ( :serialize ) do |value |
120
+ count += 1
121
+ nil
122
+ end
123
+ @type . define_singleton_method ( :changed_in_place? ) do |*|
124
+ true
125
+ end
126
+
127
+ attribute = Attribute . from_user ( nil , "whatever" , @type )
128
+
129
+ attribute . value_for_database
130
+ attribute . value_for_database
131
+ assert_equal 2 , count
132
+ end
133
+
99
134
test "duping dups the value" do
100
135
attribute = Attribute . from_database ( nil , "a value" , @type )
101
136
Original file line number Diff line number Diff line change @@ -10,7 +10,8 @@ def type_cast(value)
10
10
end
11
11
12
12
def value_for_database
13
- @value_for_database ||= super
13
+ @value_for_database = _value_for_database unless defined? ( @value_for_database )
14
+ @value_for_database
14
15
end
15
16
16
17
def with_cast_value ( value )
You can’t perform that action at this time.
0 commit comments