~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activerecord/test/cases/dirty_test.rb

  • Committer: Michael Forrest
  • Date: 2010-10-15 16:28:50 UTC
  • Revision ID: michael.forrest@canonical.com-20101015162850-tj2vchanv0kr0dun
refrozeĀ gems

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
require 'cases/helper'
 
2
require 'models/topic'    # For booleans
 
3
require 'models/pirate'   # For timestamps
 
4
require 'models/parrot'
 
5
require 'models/person'   # For optimistic locking
 
6
 
 
7
class Pirate # Just reopening it, not defining it
 
8
  attr_accessor :detected_changes_in_after_update # Boolean for if changes are detected
 
9
  attr_accessor :changes_detected_in_after_update # Actual changes
 
10
 
 
11
  after_update :check_changes
 
12
 
 
13
private
 
14
  # after_save/update in sweepers, observers, and the model itself
 
15
  # can end up checking dirty status and acting on the results
 
16
  def check_changes
 
17
    if self.changed?
 
18
      self.detected_changes_in_after_update = true
 
19
      self.changes_detected_in_after_update = self.changes
 
20
    end
 
21
  end
 
22
end
 
23
 
 
24
class NumericData < ActiveRecord::Base
 
25
  self.table_name = 'numeric_data'
 
26
end
 
27
 
 
28
class DirtyTest < ActiveRecord::TestCase
 
29
  def test_attribute_changes
 
30
    # New record - no changes.
 
31
    pirate = Pirate.new
 
32
    assert !pirate.catchphrase_changed?
 
33
    assert_nil pirate.catchphrase_change
 
34
 
 
35
    # Change catchphrase.
 
36
    pirate.catchphrase = 'arrr'
 
37
    assert pirate.catchphrase_changed?
 
38
    assert_nil pirate.catchphrase_was
 
39
    assert_equal [nil, 'arrr'], pirate.catchphrase_change
 
40
 
 
41
    # Saved - no changes.
 
42
    pirate.save!
 
43
    assert !pirate.catchphrase_changed?
 
44
    assert_nil pirate.catchphrase_change
 
45
 
 
46
    # Same value - no changes.
 
47
    pirate.catchphrase = 'arrr'
 
48
    assert !pirate.catchphrase_changed?
 
49
    assert_nil pirate.catchphrase_change
 
50
  end
 
51
 
 
52
  def test_aliased_attribute_changes
 
53
    # the actual attribute here is name, title is an
 
54
    # alias setup via alias_attribute
 
55
    parrot = Parrot.new
 
56
    assert !parrot.title_changed?
 
57
    assert_nil parrot.title_change
 
58
 
 
59
    parrot.name = 'Sam'
 
60
    assert parrot.title_changed?
 
61
    assert_nil parrot.title_was
 
62
    assert_equal parrot.name_change, parrot.title_change
 
63
  end
 
64
 
 
65
  def test_nullable_number_not_marked_as_changed_if_new_value_is_blank
 
66
    pirate = Pirate.new
 
67
 
 
68
    ["", nil].each do |value|
 
69
      pirate.parrot_id = value
 
70
      assert !pirate.parrot_id_changed?
 
71
      assert_nil pirate.parrot_id_change
 
72
    end
 
73
  end
 
74
 
 
75
  def test_nullable_decimal_not_marked_as_changed_if_new_value_is_blank
 
76
    numeric_data = NumericData.new
 
77
 
 
78
    ["", nil].each do |value|
 
79
      numeric_data.bank_balance = value
 
80
      assert !numeric_data.bank_balance_changed?
 
81
      assert_nil numeric_data.bank_balance_change
 
82
    end
 
83
  end
 
84
 
 
85
  def test_nullable_float_not_marked_as_changed_if_new_value_is_blank
 
86
    numeric_data = NumericData.new
 
87
 
 
88
    ["", nil].each do |value|
 
89
      numeric_data.temperature = value
 
90
      assert !numeric_data.temperature_changed?
 
91
      assert_nil numeric_data.temperature_change
 
92
    end
 
93
  end
 
94
 
 
95
  def test_nullable_integer_zero_to_string_zero_not_marked_as_changed
 
96
    pirate = Pirate.new
 
97
    pirate.parrot_id = 0
 
98
    pirate.catchphrase = 'arrr'
 
99
    assert pirate.save!
 
100
 
 
101
    assert !pirate.changed?
 
102
 
 
103
    pirate.parrot_id = '0'
 
104
    assert !pirate.changed?
 
105
  end
 
106
 
 
107
  def test_zero_to_blank_marked_as_changed
 
108
    pirate = Pirate.new
 
109
    pirate.catchphrase = "Yarrrr, me hearties"
 
110
    pirate.parrot_id = 1
 
111
    pirate.save
 
112
 
 
113
    # check the change from 1 to ''
 
114
    pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
 
115
    pirate.parrot_id = ''
 
116
    assert pirate.parrot_id_changed?
 
117
    assert_equal([1, nil], pirate.parrot_id_change)
 
118
    pirate.save
 
119
 
 
120
    # check the change from nil to 0
 
121
    pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
 
122
    pirate.parrot_id = 0
 
123
    assert pirate.parrot_id_changed?
 
124
    assert_equal([nil, 0], pirate.parrot_id_change)
 
125
    pirate.save
 
126
 
 
127
    # check the change from 0 to ''
 
128
    pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
 
129
    pirate.parrot_id = ''
 
130
    assert pirate.parrot_id_changed?
 
131
    assert_equal([0, nil], pirate.parrot_id_change)
 
132
  end
 
133
 
 
134
  def test_object_should_be_changed_if_any_attribute_is_changed
 
135
    pirate = Pirate.new
 
136
    assert !pirate.changed?
 
137
    assert_equal [], pirate.changed
 
138
    assert_equal Hash.new, pirate.changes
 
139
 
 
140
    pirate.catchphrase = 'arrr'
 
141
    assert pirate.changed?
 
142
    assert_nil pirate.catchphrase_was
 
143
    assert_equal %w(catchphrase), pirate.changed
 
144
    assert_equal({'catchphrase' => [nil, 'arrr']}, pirate.changes)
 
145
 
 
146
    pirate.save
 
147
    assert !pirate.changed?
 
148
    assert_equal [], pirate.changed
 
149
    assert_equal Hash.new, pirate.changes
 
150
  end
 
151
 
 
152
  def test_attribute_will_change!
 
153
    pirate = Pirate.create!(:catchphrase => 'arr')
 
154
 
 
155
    pirate.catchphrase << ' matey'
 
156
    assert !pirate.catchphrase_changed?
 
157
 
 
158
    assert pirate.catchphrase_will_change!
 
159
    assert pirate.catchphrase_changed?
 
160
    assert_equal ['arr matey', 'arr matey'], pirate.catchphrase_change
 
161
 
 
162
    pirate.catchphrase << '!'
 
163
    assert pirate.catchphrase_changed?
 
164
    assert_equal ['arr matey', 'arr matey!'], pirate.catchphrase_change
 
165
  end
 
166
 
 
167
  def test_association_assignment_changes_foreign_key
 
168
    pirate = Pirate.create!(:catchphrase => 'jarl')
 
169
    pirate.parrot = Parrot.create!(:name => 'Lorre')
 
170
    assert pirate.changed?
 
171
    assert_equal %w(parrot_id), pirate.changed
 
172
  end
 
173
 
 
174
  def test_attribute_should_be_compared_with_type_cast
 
175
    topic = Topic.new
 
176
    assert topic.approved?
 
177
    assert !topic.approved_changed?
 
178
 
 
179
    # Coming from web form.
 
180
    params = {:topic => {:approved => 1}}
 
181
    # In the controller.
 
182
    topic.attributes = params[:topic]
 
183
    assert topic.approved?
 
184
    assert !topic.approved_changed?
 
185
  end
 
186
 
 
187
  def test_partial_update
 
188
    pirate = Pirate.new(:catchphrase => 'foo')
 
189
    old_updated_on = 1.hour.ago.beginning_of_day
 
190
 
 
191
    with_partial_updates Pirate, false do
 
192
      assert_queries(2) { 2.times { pirate.save! } }
 
193
      Pirate.update_all({ :updated_on => old_updated_on }, :id => pirate.id)
 
194
    end
 
195
 
 
196
    with_partial_updates Pirate, true do
 
197
      assert_queries(0) { 2.times { pirate.save! } }
 
198
      assert_equal old_updated_on, pirate.reload.updated_on
 
199
 
 
200
      assert_queries(1) { pirate.catchphrase = 'bar'; pirate.save! }
 
201
      assert_not_equal old_updated_on, pirate.reload.updated_on
 
202
    end
 
203
  end
 
204
 
 
205
  def test_partial_update_with_optimistic_locking
 
206
    person = Person.new(:first_name => 'foo')
 
207
    old_lock_version = 1
 
208
 
 
209
    with_partial_updates Person, false do
 
210
      assert_queries(2) { 2.times { person.save! } }
 
211
      Person.update_all({ :first_name => 'baz' }, :id => person.id)
 
212
    end
 
213
 
 
214
    with_partial_updates Person, true do
 
215
      assert_queries(0) { 2.times { person.save! } }
 
216
      assert_equal old_lock_version, person.reload.lock_version
 
217
 
 
218
      assert_queries(1) { person.first_name = 'bar'; person.save! }
 
219
      assert_not_equal old_lock_version, person.reload.lock_version
 
220
    end
 
221
  end
 
222
 
 
223
  def test_changed_attributes_should_be_preserved_if_save_failure
 
224
    pirate = Pirate.new
 
225
    pirate.parrot_id = 1
 
226
    assert !pirate.save
 
227
    check_pirate_after_save_failure(pirate)
 
228
 
 
229
    pirate = Pirate.new
 
230
    pirate.parrot_id = 1
 
231
    assert_raise(ActiveRecord::RecordInvalid) { pirate.save! }
 
232
    check_pirate_after_save_failure(pirate)
 
233
  end
 
234
 
 
235
  def test_reload_should_clear_changed_attributes
 
236
    pirate = Pirate.create!(:catchphrase => "shiver me timbers")
 
237
    pirate.catchphrase = "*hic*"
 
238
    assert pirate.changed?
 
239
    pirate.reload
 
240
    assert !pirate.changed?
 
241
  end
 
242
 
 
243
  def test_reverted_changes_are_not_dirty
 
244
    phrase = "shiver me timbers"
 
245
    pirate = Pirate.create!(:catchphrase => phrase)
 
246
    pirate.catchphrase = "*hic*"
 
247
    assert pirate.changed?
 
248
    pirate.catchphrase = phrase
 
249
    assert !pirate.changed?
 
250
  end
 
251
 
 
252
  def test_reverted_changes_are_not_dirty_after_multiple_changes
 
253
    phrase = "shiver me timbers"
 
254
    pirate = Pirate.create!(:catchphrase => phrase)
 
255
    10.times do |i|
 
256
      pirate.catchphrase = "*hic*" * i
 
257
      assert pirate.changed?
 
258
    end
 
259
    assert pirate.changed?
 
260
    pirate.catchphrase = phrase
 
261
    assert !pirate.changed?
 
262
  end
 
263
 
 
264
 
 
265
  def test_reverted_changes_are_not_dirty_going_from_nil_to_value_and_back
 
266
    pirate = Pirate.create!(:catchphrase => "Yar!")
 
267
 
 
268
    pirate.parrot_id = 1
 
269
    assert pirate.changed?
 
270
    assert pirate.parrot_id_changed?
 
271
    assert !pirate.catchphrase_changed?
 
272
 
 
273
    pirate.parrot_id = nil
 
274
    assert !pirate.changed?
 
275
    assert !pirate.parrot_id_changed?
 
276
    assert !pirate.catchphrase_changed?
 
277
  end
 
278
 
 
279
  def test_save_should_store_serialized_attributes_even_with_partial_updates
 
280
    with_partial_updates(Topic) do
 
281
      topic = Topic.create!(:content => {:a => "a"})
 
282
      topic.content[:b] = "b"
 
283
      #assert topic.changed? # Known bug, will fail
 
284
      topic.save!
 
285
      assert_equal "b", topic.content[:b]
 
286
      topic.reload
 
287
      assert_equal "b", topic.content[:b]
 
288
    end
 
289
  end
 
290
 
 
291
  def test_save_should_not_save_serialized_attribute_with_partial_updates_if_not_present
 
292
    with_partial_updates(Topic) do
 
293
      Topic.create!(:author_name => 'Bill', :content => {:a => "a"})
 
294
      topic = Topic.first(:select => 'id, author_name')
 
295
      topic.update_attribute :author_name, 'John'
 
296
      topic = Topic.first
 
297
      assert_not_nil topic.content
 
298
    end
 
299
  end
 
300
 
 
301
  private
 
302
    def with_partial_updates(klass, on = true)
 
303
      old = klass.partial_updates?
 
304
      klass.partial_updates = on
 
305
      yield
 
306
    ensure
 
307
      klass.partial_updates = old
 
308
    end
 
309
 
 
310
    def check_pirate_after_save_failure(pirate)
 
311
      assert pirate.changed?
 
312
      assert pirate.parrot_id_changed?
 
313
      assert_equal %w(parrot_id), pirate.changed
 
314
      assert_nil pirate.parrot_id_was
 
315
    end
 
316
end