Froze rails gems
[depot.git] / vendor / rails / activerecord / test / cases / dirty_test.rb
diff --git a/vendor/rails/activerecord/test/cases/dirty_test.rb b/vendor/rails/activerecord/test/cases/dirty_test.rb
new file mode 100644 (file)
index 0000000..39d38c4
--- /dev/null
@@ -0,0 +1,270 @@
+require 'cases/helper'
+require 'models/topic'    # For booleans
+require 'models/pirate'   # For timestamps
+require 'models/parrot'
+require 'models/person'   # For optimistic locking
+
+class Pirate # Just reopening it, not defining it
+  attr_accessor :detected_changes_in_after_update # Boolean for if changes are detected
+  attr_accessor :changes_detected_in_after_update # Actual changes
+
+  after_update :check_changes
+
+private
+  # after_save/update in sweepers, observers, and the model itself
+  # can end up checking dirty status and acting on the results
+  def check_changes
+    if self.changed?
+      self.detected_changes_in_after_update = true
+      self.changes_detected_in_after_update = self.changes
+    end
+  end
+end
+
+class DirtyTest < ActiveRecord::TestCase
+  def test_attribute_changes
+    # New record - no changes.
+    pirate = Pirate.new
+    assert !pirate.catchphrase_changed?
+    assert_nil pirate.catchphrase_change
+
+    # Change catchphrase.
+    pirate.catchphrase = 'arrr'
+    assert pirate.catchphrase_changed?
+    assert_nil pirate.catchphrase_was
+    assert_equal [nil, 'arrr'], pirate.catchphrase_change
+
+    # Saved - no changes.
+    pirate.save!
+    assert !pirate.catchphrase_changed?
+    assert_nil pirate.catchphrase_change
+
+    # Same value - no changes.
+    pirate.catchphrase = 'arrr'
+    assert !pirate.catchphrase_changed?
+    assert_nil pirate.catchphrase_change
+  end
+
+  def test_aliased_attribute_changes
+    # the actual attribute here is name, title is an
+    # alias setup via alias_attribute
+    parrot = Parrot.new
+    assert !parrot.title_changed?
+    assert_nil parrot.title_change
+
+    parrot.name = 'Sam'
+    assert parrot.title_changed?
+    assert_nil parrot.title_was
+    assert_equal parrot.name_change, parrot.title_change
+  end
+
+  def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank
+    pirate = Pirate.new
+
+    ["", nil].each do |value|
+      pirate.parrot_id = value
+      assert !pirate.parrot_id_changed?
+      assert_nil pirate.parrot_id_change
+    end
+  end
+
+  def test_zero_to_blank_marked_as_changed
+    pirate = Pirate.new
+    pirate.catchphrase = "Yarrrr, me hearties"
+    pirate.parrot_id = 1
+    pirate.save
+
+    # check the change from 1 to ''
+    pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
+    pirate.parrot_id = ''
+    assert pirate.parrot_id_changed?
+    assert_equal([1, nil], pirate.parrot_id_change)
+    pirate.save
+
+    # check the change from nil to 0
+    pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
+    pirate.parrot_id = 0
+    assert pirate.parrot_id_changed?
+    assert_equal([nil, 0], pirate.parrot_id_change)
+    pirate.save
+
+    # check the change from 0 to ''
+    pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
+    pirate.parrot_id = ''
+    assert pirate.parrot_id_changed?
+    assert_equal([0, nil], pirate.parrot_id_change)
+  end
+
+  def test_object_should_be_changed_if_any_attribute_is_changed
+    pirate = Pirate.new
+    assert !pirate.changed?
+    assert_equal [], pirate.changed
+    assert_equal Hash.new, pirate.changes
+
+    pirate.catchphrase = 'arrr'
+    assert pirate.changed?
+    assert_nil pirate.catchphrase_was
+    assert_equal %w(catchphrase), pirate.changed
+    assert_equal({'catchphrase' => [nil, 'arrr']}, pirate.changes)
+
+    pirate.save
+    assert !pirate.changed?
+    assert_equal [], pirate.changed
+    assert_equal Hash.new, pirate.changes
+  end
+
+  def test_attribute_will_change!
+    pirate = Pirate.create!(:catchphrase => 'arr')
+
+    pirate.catchphrase << ' matey'
+    assert !pirate.catchphrase_changed?
+
+    assert pirate.catchphrase_will_change!
+    assert pirate.catchphrase_changed?
+    assert_equal ['arr matey', 'arr matey'], pirate.catchphrase_change
+
+    pirate.catchphrase << '!'
+    assert pirate.catchphrase_changed?
+    assert_equal ['arr matey', 'arr matey!'], pirate.catchphrase_change
+  end
+
+  def test_association_assignment_changes_foreign_key
+    pirate = Pirate.create!(:catchphrase => 'jarl')
+    pirate.parrot = Parrot.create!
+    assert pirate.changed?
+    assert_equal %w(parrot_id), pirate.changed
+  end
+
+  def test_attribute_should_be_compared_with_type_cast
+    topic = Topic.new
+    assert topic.approved?
+    assert !topic.approved_changed?
+
+    # Coming from web form.
+    params = {:topic => {:approved => 1}}
+    # In the controller.
+    topic.attributes = params[:topic]
+    assert topic.approved?
+    assert !topic.approved_changed?
+  end
+
+  def test_partial_update
+    pirate = Pirate.new(:catchphrase => 'foo')
+    old_updated_on = 1.hour.ago.beginning_of_day
+
+    with_partial_updates Pirate, false do
+      assert_queries(2) { 2.times { pirate.save! } }
+      Pirate.update_all({ :updated_on => old_updated_on }, :id => pirate.id)
+    end
+
+    with_partial_updates Pirate, true do
+      assert_queries(0) { 2.times { pirate.save! } }
+      assert_equal old_updated_on, pirate.reload.updated_on
+
+      assert_queries(1) { pirate.catchphrase = 'bar'; pirate.save! }
+      assert_not_equal old_updated_on, pirate.reload.updated_on
+    end
+  end
+
+  def test_partial_update_with_optimistic_locking
+    person = Person.new(:first_name => 'foo')
+    old_lock_version = 1
+
+    with_partial_updates Person, false do
+      assert_queries(2) { 2.times { person.save! } }
+      Person.update_all({ :first_name => 'baz' }, :id => person.id)
+    end
+
+    with_partial_updates Person, true do
+      assert_queries(0) { 2.times { person.save! } }
+      assert_equal old_lock_version, person.reload.lock_version
+
+      assert_queries(1) { person.first_name = 'bar'; person.save! }
+      assert_not_equal old_lock_version, person.reload.lock_version
+    end
+  end
+
+  def test_changed_attributes_should_be_preserved_if_save_failure
+    pirate = Pirate.new
+    pirate.parrot_id = 1
+    assert !pirate.save
+    check_pirate_after_save_failure(pirate)
+
+    pirate = Pirate.new
+    pirate.parrot_id = 1
+    assert_raises(ActiveRecord::RecordInvalid) { pirate.save! }
+    check_pirate_after_save_failure(pirate)
+  end
+
+  def test_reload_should_clear_changed_attributes
+    pirate = Pirate.create!(:catchphrase => "shiver me timbers")
+    pirate.catchphrase = "*hic*"
+    assert pirate.changed?
+    pirate.reload
+    assert !pirate.changed?
+  end
+
+  def test_reverted_changes_are_not_dirty
+    phrase = "shiver me timbers"
+    pirate = Pirate.create!(:catchphrase => phrase)
+    pirate.catchphrase = "*hic*"
+    assert pirate.changed?
+    pirate.catchphrase = phrase
+    assert !pirate.changed?
+  end
+
+  def test_reverted_changes_are_not_dirty_after_multiple_changes
+    phrase = "shiver me timbers"
+    pirate = Pirate.create!(:catchphrase => phrase)
+    10.times do |i|
+      pirate.catchphrase = "*hic*" * i
+      assert pirate.changed?
+    end
+    assert pirate.changed?
+    pirate.catchphrase = phrase
+    assert !pirate.changed?
+  end
+
+
+  def test_reverted_changes_are_not_dirty_going_from_nil_to_value_and_back
+    pirate = Pirate.create!(:catchphrase => "Yar!")
+
+    pirate.parrot_id = 1
+    assert pirate.changed?
+    assert pirate.parrot_id_changed?
+    assert !pirate.catchphrase_changed?
+
+    pirate.parrot_id = nil
+    assert !pirate.changed?
+    assert !pirate.parrot_id_changed?
+    assert !pirate.catchphrase_changed?
+  end
+
+  def test_save_should_store_serialized_attributes_even_with_partial_updates
+    with_partial_updates(Topic) do
+      topic = Topic.create!(:content => {:a => "a"})
+      topic.content[:b] = "b"
+      #assert topic.changed? # Known bug, will fail
+      topic.save!
+      assert_equal "b", topic.content[:b]
+      topic.reload
+      assert_equal "b", topic.content[:b]
+    end
+  end
+
+  private
+    def with_partial_updates(klass, on = true)
+      old = klass.partial_updates?
+      klass.partial_updates = on
+      yield
+    ensure
+      klass.partial_updates = old
+    end
+
+    def check_pirate_after_save_failure(pirate)
+      assert pirate.changed?
+      assert pirate.parrot_id_changed?
+      assert_equal %w(parrot_id), pirate.changed
+      assert_nil pirate.parrot_id_was
+    end
+end