class OptimisticLockingTest

Public Instance Methods

test_explicit_update_lock_column_raise_error() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 197
def test_explicit_update_lock_column_raise_error
  person = Person.find(1)

  assert_raises(ActiveRecord::StaleObjectError) do
    person.first_name = "Douglas Adams"
    person.lock_version = 42

    assert person.lock_version_changed?

    person.save
  end
end
test_lock_column_is_mass_assignable() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 225
def test_lock_column_is_mass_assignable
  p1 = Person.create(first_name: "bianca")
  assert_equal 0, p1.lock_version
  assert_equal p1.lock_version, Person.new(p1.attributes).lock_version

  p1.first_name = "bianca2"
  p1.save!
  assert_equal 1, p1.lock_version
  assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
end
test_lock_column_name_existing() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 210
def test_lock_column_name_existing
  t1 = LegacyThing.find(1)
  t2 = LegacyThing.find(1)
  assert_equal 0, t1.version
  assert_equal 0, t2.version

  t1.tps_report_number = 700
  t1.save!
  assert_equal 1, t1.version
  assert_equal 0, t2.version

  t2.tps_report_number = 800
  assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
end
test_lock_destroy() click to toggle source

See Lighthouse ticket #1966

# File activerecord/test/cases/locking_test.rb, line 93
def test_lock_destroy
  p1 = Person.find(1)
  p2 = Person.find(1)
  assert_equal 0, p1.lock_version
  assert_equal 0, p2.lock_version

  p1.first_name = "stu"
  p1.save!
  assert_equal 1, p1.lock_version
  assert_equal 0, p2.lock_version

  assert_raises(ActiveRecord::StaleObjectError) { p2.destroy }

  assert p1.destroy
  assert p1.frozen?
  assert p1.destroyed?
  assert_raises(ActiveRecord::RecordNotFound) { Person.find(1) }
end
test_lock_exception_record() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 148
def test_lock_exception_record
  p1 = Person.new(first_name: "mira")
  assert_equal 0, p1.lock_version

  p1.first_name = "mira2"
  p1.save!
  p2 = Person.find(p1.id)
  assert_equal 0, p1.lock_version
  assert_equal 0, p2.lock_version

  p1.first_name = "mira3"
  p1.save!

  p2.first_name = "sue"
  error = assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
  assert_equal(error.record.object_id, p2.object_id)
end
test_lock_existing() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 77
def test_lock_existing
  p1 = Person.find(1)
  p2 = Person.find(1)
  assert_equal 0, p1.lock_version
  assert_equal 0, p2.lock_version

  p1.first_name = "stu"
  p1.save!
  assert_equal 1, p1.lock_version
  assert_equal 0, p2.lock_version

  p2.first_name = "sue"
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
end
test_lock_new() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 129
def test_lock_new
  p1 = Person.new(first_name: "anika")
  assert_equal 0, p1.lock_version

  p1.first_name = "anika2"
  p1.save!
  p2 = Person.find(p1.id)
  assert_equal 0, p1.lock_version
  assert_equal 0, p2.lock_version

  p1.first_name = "anika3"
  p1.save!
  assert_equal 1, p1.lock_version
  assert_equal 0, p2.lock_version

  p2.first_name = "sue"
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
end
test_lock_new_when_explicitly_passing_nil() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 166
def test_lock_new_when_explicitly_passing_nil
  p1 = Person.new(first_name: "anika", lock_version: nil)
  p1.save!
  assert_equal 0, p1.lock_version
end
test_lock_new_when_explicitly_passing_value() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 172
def test_lock_new_when_explicitly_passing_value
  p1 = Person.new(first_name: "Douglas Adams", lock_version: 42)
  p1.save!
  assert_equal 42, p1.lock_version
end
test_lock_repeating() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 112
def test_lock_repeating
  p1 = Person.find(1)
  p2 = Person.find(1)
  assert_equal 0, p1.lock_version
  assert_equal 0, p2.lock_version

  p1.first_name = "stu"
  p1.save!
  assert_equal 1, p1.lock_version
  assert_equal 0, p2.lock_version

  p2.first_name = "sue"
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
  p2.first_name = "sue2"
  assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
end
test_lock_with_custom_column_without_default_queries_count() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 351
def test_lock_with_custom_column_without_default_queries_count
  t1 = LockWithCustomColumnWithoutDefault.create(title: "title1")

  assert_equal "title1", t1.title
  assert_equal 0, t1.custom_lock_version

  assert_queries(1) { t1.update(title: "title2") }

  t1.reload
  assert_equal "title2", t1.title
  assert_equal 1, t1.custom_lock_version

  t2 = LockWithCustomColumnWithoutDefault.new(title: "title1")

  assert_queries(1) { t2.save! }

  t2.reload
  assert_equal "title1", t2.title
  assert_equal 0, t2.custom_lock_version
end
test_lock_with_custom_column_without_default_sets_version_to_zero() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 315
def test_lock_with_custom_column_without_default_sets_version_to_zero
  t1 = LockWithCustomColumnWithoutDefault.new

  assert_equal 0, t1.custom_lock_version
  assert_nil t1.custom_lock_version_before_type_cast

  t1.save!
  t1.reload

  assert_equal 0, t1.custom_lock_version
  assert_equal 0, t1.custom_lock_version_before_type_cast
end
test_lock_with_custom_column_without_default_should_work_with_null_in_the_database() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 328
def test_lock_with_custom_column_without_default_should_work_with_null_in_the_database
  ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults_cust(title) VALUES('title1')")

  t1 = LockWithCustomColumnWithoutDefault.last
  t2 = LockWithCustomColumnWithoutDefault.find(t1.id)

  assert_equal 0, t1.custom_lock_version
  assert_nil t1.custom_lock_version_before_type_cast
  assert_equal 0, t2.custom_lock_version
  assert_nil t2.custom_lock_version_before_type_cast

  t1.title = "new title1"
  t2.title = "new title2"

  assert_nothing_raised { t1.save! }
  assert_equal 1, t1.custom_lock_version
  assert_equal "new title1", t1.title

  assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
  assert_equal 0, t2.custom_lock_version
  assert_equal "new title2", t2.title
end
test_lock_without_default_queries_count() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 294
def test_lock_without_default_queries_count
  t1 = LockWithoutDefault.create(title: "title1")

  assert_equal "title1", t1.title
  assert_equal 0, t1.lock_version

  assert_queries(1) { t1.update(title: "title2") }

  t1.reload
  assert_equal "title2", t1.title
  assert_equal 1, t1.lock_version

  t2 = LockWithoutDefault.new(title: "title1")

  assert_queries(1) { t2.save! }

  t2.reload
  assert_equal "title1", t2.title
  assert_equal 0, t2.lock_version
end
test_lock_without_default_sets_version_to_zero() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 236
def test_lock_without_default_sets_version_to_zero
  t1 = LockWithoutDefault.new

  assert_equal 0, t1.lock_version
  assert_nil t1.lock_version_before_type_cast

  t1.save!
  t1.reload

  assert_equal 0, t1.lock_version
  assert_equal 0, t1.lock_version_before_type_cast
end
test_lock_without_default_should_work_with_null_in_the_database() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 272
def test_lock_without_default_should_work_with_null_in_the_database
  ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
  t1 = LockWithoutDefault.last
  t2 = LockWithoutDefault.find(t1.id)

  assert_equal 0, t1.lock_version
  assert_nil t1.lock_version_before_type_cast
  assert_equal 0, t2.lock_version
  assert_nil t2.lock_version_before_type_cast

  t1.title = "new title1"
  t2.title = "new title2"

  assert_nothing_raised { t1.save! }
  assert_equal 1, t1.lock_version
  assert_equal "new title1", t1.title

  assert_raise(ActiveRecord::StaleObjectError) { t2.save! }
  assert_equal 0, t2.lock_version
  assert_equal "new title2", t2.title
end
test_non_integer_lock_destroy() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 59
def test_non_integer_lock_destroy
  s1 = StringKeyObject.find("record1")
  s2 = StringKeyObject.find("record1")
  assert_equal 0, s1.lock_version
  assert_equal 0, s2.lock_version

  s1.name = "updated record"
  s1.save!
  assert_equal 1, s1.lock_version
  assert_equal 0, s2.lock_version
  assert_raise(ActiveRecord::StaleObjectError) { s2.destroy }

  assert s1.destroy
  assert s1.frozen?
  assert s1.destroyed?
  assert_raises(ActiveRecord::RecordNotFound) { StringKeyObject.find("record1") }
end
test_non_integer_lock_existing() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 44
def test_non_integer_lock_existing
  s1 = StringKeyObject.find("record1")
  s2 = StringKeyObject.find("record1")
  assert_equal 0, s1.lock_version
  assert_equal 0, s2.lock_version

  s1.name = "updated record"
  s1.save!
  assert_equal 1, s1.lock_version
  assert_equal 0, s2.lock_version

  s2.name = "doubly updated record"
  assert_raise(ActiveRecord::StaleObjectError) { s2.save! }
end
test_polymorphic_destroy_with_dependencies_and_lock_version() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 402
def test_polymorphic_destroy_with_dependencies_and_lock_version
  car = Car.create!

  assert_difference "car.wheels.count"  do
    car.wheels << Wheel.create!
  end
  assert_difference "car.wheels.count", -1  do
    car.reload.destroy
  end
  assert car.destroyed?
end
test_quote_table_name() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 384
def test_quote_table_name
  ref = references(:michael_magician)
  ref.favourite = !ref.favourite
  assert ref.save
end
test_quote_value_passed_lock_col() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 34
def test_quote_value_passed_lock_col
  p1 = Person.find(1)
  assert_equal 0, p1.lock_version

  p1.first_name = "anika2"
  p1.save!

  assert_equal 1, p1.lock_version
end
test_readonly_attributes() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 372
def test_readonly_attributes
  assert_equal Set.new([ "name" ]), ReadonlyNameShip.readonly_attributes

  s = ReadonlyNameShip.create(name: "unchangeable name")
  s.reload
  assert_equal "unchangeable name", s.name

  s.update(name: "changed name")
  s.reload
  assert_equal "unchangeable name", s.name
end
test_removing_has_and_belongs_to_many_associations_upon_destroy() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 414
def test_removing_has_and_belongs_to_many_associations_upon_destroy
  p = RichPerson.create! first_name: "Jon"
  p.treasures.create!
  assert !p.treasures.empty?
  p.destroy
  assert p.treasures.empty?
  assert RichPerson.connection.select_all("SELECT * FROM peoples_treasures WHERE rich_person_id = 1").empty?
end
test_touch_existing_lock() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 178
def test_touch_existing_lock
  p1 = Person.find(1)
  assert_equal 0, p1.lock_version

  p1.touch
  assert_equal 1, p1.lock_version
  assert_not p1.changed?, "Changes should have been cleared"
end
test_touch_existing_lock_without_default_should_work_with_null_in_the_database() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 249
def test_touch_existing_lock_without_default_should_work_with_null_in_the_database
  ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')")
  t1 = LockWithoutDefault.last

  assert_equal 0, t1.lock_version
  assert_nil t1.lock_version_before_type_cast

  t1.touch

  assert_equal 1, t1.lock_version
end
test_touch_stale_object() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 187
def test_touch_stale_object
  person = Person.create!(first_name: "Mehmet Emin")
  stale_person = Person.find(person.id)
  person.update_attribute(:gender, "M")

  assert_raises(ActiveRecord::StaleObjectError) do
    stale_person.touch
  end
end
test_touch_stale_object_with_lock_without_default() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 261
def test_touch_stale_object_with_lock_without_default
  t1 = LockWithoutDefault.create!(title: "title1")
  stale_object = LockWithoutDefault.find(t1.id)

  t1.update!(title: "title2")

  assert_raises(ActiveRecord::StaleObjectError) do
    stale_object.touch
  end
end
test_update_without_attributes_does_not_only_update_lock_version() click to toggle source

Useful for partial updates, don't only update the lock_version if there is nothing else being updated.

# File activerecord/test/cases/locking_test.rb, line 392
def test_update_without_attributes_does_not_only_update_lock_version
  assert_nothing_raised do
    p1 = Person.create!(first_name: "anika")
    lock_version = p1.lock_version
    p1.save
    p1.reload
    assert_equal lock_version, p1.lock_version
  end
end
test_yaml_dumping_with_lock_column() click to toggle source
# File activerecord/test/cases/locking_test.rb, line 423
def test_yaml_dumping_with_lock_column
  t1 = LockWithoutDefault.new
  t2 = YAML.load(YAML.dump(t1))

  assert_equal t1.attributes, t2.attributes
end