From 8905c1fb496641c3cdb7b3b816ae6d3d4b2c2b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Tue, 21 Aug 2012 10:13:55 -0300 Subject: Merge pull request #6986 from kennyj/fix_6975 Fix #6975. Round usec when writing timestamp attribute. Conflicts: activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb --- activerecord/CHANGELOG.md | 5 +++++ .../attribute_methods/time_zone_conversion.rb | 19 ++++++++++++++----- activerecord/test/cases/dirty_test.rb | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 9c063e897c..6f81625429 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,10 @@ ## Rails 3.2.9 (unreleased) +* Round usec when comparing timestamp attributes in the dirty tracking. + Fixes #6975. + + *kennyj* + * Use inversed parent for first and last child of has_many association. *Ravil Bayramgalin* 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 7abe29c7d5..4c3d5eed4c 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -41,11 +41,14 @@ module ActiveRecord unless time.acts_like?(:time) 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 - write_attribute(:#{attr_name}, original_time) - #{attr_name}_will_change! if changed - @attributes_cache["#{attr_name}"] = time + zoned_time = time && time.in_time_zone rescue nil + rounded_time = round_usec(zoned_time) + rounded_value = round_usec(read_attribute("#{attr_name}")) + if (rounded_value != rounded_time) || (!rounded_value && original_time) + write_attribute("#{attr_name}", original_time) + #{attr_name}_will_change! + @attributes_cache["#{attr_name}"] = zoned_time + end end EOV generated_attribute_methods.module_eval(method_body, __FILE__, line) @@ -59,6 +62,12 @@ module ActiveRecord time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(name.to_sym) && column.type.in?([:datetime, :timestamp]) end end + + private + def round_usec(value) + return unless value + value.change(:usec => 0) + end end end end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 26afd203d2..3bd2e909d7 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -521,6 +521,21 @@ class DirtyTest < ActiveRecord::TestCase assert !pirate.previous_changes.key?('created_on') end + def test_setting_time_attributes_with_time_zone_field_to_same_time_should_not_be_marked_as_a_change + in_time_zone 'Paris' do + target = Class.new(ActiveRecord::Base) + target.table_name = 'pirates' + + created_on = Time.now + + pirate = target.create(:created_on => created_on) + pirate.reload # Here mysql truncate the usec value to 0 + + pirate.created_on = created_on + assert !pirate.created_on_changed? + end + end + private def with_partial_updates(klass, on = true) old = klass.partial_updates? -- cgit v1.2.3