rails/rails — pull request #9489 by obrie (2013-02-28 14:47:53+00:00)
Title: Fix overridden column defaults not getting marked as changed for new records

TL;DR; ActiveRecord locking column defaults don't get persisted

__Premise__: In `ActiveRecord::Locking::Optimistic#column_defaults` we set the default value for the locking column to `0` if it's not already set by the database.

__Problem__: Due to the introduction of partial inserts @ 144e8691cbfb8bba77f18cfe68d5e7fd48887f5e, this overridden default will get ignored and never persisted to the database. This results in the locking column having a `nil` value for new records. The reason this happens is because `ActiveRecord::AttributeMethods::Dirty#keys_for_partial_write` will skip writing attributes that are not marked as changed. When a new record's default attributes are set, the list of changed attributes is always assumed to be empty -- we don't actually check to verify that.

__Solution__: When a new record's default attributes are set, *also* initialize the list of changed attributes by comparing current values against what's stored as the column defaults. This initialization step intentionally does not use the `#column_defaults` helper since that's what's used by `ActiveRecord::Locking::Optimistic` to set the overridden default in the first place.

__Verification__: Two existing locking tests have been modified to verify that they're locking column defaults are persisted to the database. These tests were failing prior to this change.

This change will also fix other libraries that have been relying on this behavior.