diff options
author | Lilibeth De La Cruz <lilibethdlc@gmail.com> | 2013-01-25 04:14:27 -0400 |
---|---|---|
committer | Andrew White <andyw@pixeltrix.co.uk> | 2013-02-17 16:19:09 +0000 |
commit | 3c5f631caa160c2e5f4ec3ee0b7536a474b7b98f (patch) | |
tree | 40964c101787515d4ad92bc6deda2b16e6b37311 /activerecord | |
parent | f7c845745313efc23e9020dea93b5fd9ca104568 (diff) | |
download | rails-3c5f631caa160c2e5f4ec3ee0b7536a474b7b98f.tar.gz rails-3c5f631caa160c2e5f4ec3ee0b7536a474b7b98f.tar.bz2 rails-3c5f631caa160c2e5f4ec3ee0b7536a474b7b98f.zip |
Fix handling of dirty time zone aware attributes
Previously, when `time_zone_aware_attributes` were enabled, after
changing a datetime or timestamp attribute and then changing it back
to the original value, `changed_attributes` still tracked the
attribute as changed. This caused `[attribute]_changed?` and
`changed?` methods to return true incorrectly.
Example:
in_time_zone 'Paris' do
order = Order.new
original_time = Time.local(2012, 10, 10)
order.shipped_at = original_time
order.save
order.changed? # => false
# changing value
order.shipped_at = Time.local(2013, 1, 1)
order.changed? # => true
# reverting to original value
order.shipped_at = original_time
order.changed? # => false, used to return true
end
(cherry picked from commit bc982cbcb34129ea2cfe8aa1f8e0b40e444e68db)
Conflicts:
activerecord/CHANGELOG.md
activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
Backport of #9073
Fixes #8898
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 31 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb | 4 | ||||
-rw-r--r-- | activerecord/test/cases/dirty_test.rb | 2 |
3 files changed, 35 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index b0e0d56990..febead3067 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,36 @@ ## unreleased ## +* Fix handling of dirty time zone aware attributes + + Previously, when `time_zone_aware_attributes` were enabled, after + changing a datetime or timestamp attribute and then changing it back + to the original value, `changed_attributes` still tracked the + attribute as changed. This caused `[attribute]_changed?` and + `changed?` methods to return true incorrectly. + + Example: + + in_time_zone 'Paris' do + order = Order.new + original_time = Time.local(2012, 10, 10) + order.shipped_at = original_time + order.save + order.changed? # => false + + # changing value + order.shipped_at = Time.local(2013, 1, 1) + order.changed? # => true + + # reverting to original value + order.shipped_at = original_time + order.changed? # => false, used to return true + end + + Backport of #9073 + Fixes #8898 + + *Lilibeth De La Cruz* + * Fix counter cache columns not updated when replacing `has_many :through` associations. Backport #8400. diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 45810322de..6f3112e654 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -43,9 +43,9 @@ module ActiveRecord time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time end time = time.in_time_zone rescue nil if time - changed = read_attribute(:#{attr_name}) != time + previous_time = attribute_changed?("#{attr_name}") ? changed_attributes["#{attr_name}"] : read_attribute(:#{attr_name}) write_attribute(:#{attr_name}, original_time) - #{attr_name}_will_change! if changed + #{attr_name}_will_change! if previous_time != time @attributes_cache["#{attr_name}"] = time end EOV diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index b4e43bdfbc..9756c182b9 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -76,6 +76,8 @@ class DirtyTest < ActiveRecord::TestCase assert pirate.created_on_changed? assert_kind_of ActiveSupport::TimeWithZone, pirate.created_on_was assert_equal old_created_on, pirate.created_on_was + pirate.created_on = old_created_on + assert !pirate.created_on_changed? end end |