tz_time's fix_timezone reinterprets a record's tz_time attributes as local time even when they haven't been set by the user. If you simply load a record and then save it the attribute will be reinterpreted as local. You normally don't stumble across this because if you call the attr_reader the problem doesn't occur.
For example:
class Promotion < ActiveRecord::Base
tz_time_attributes :valid_from
end
TzTime.zone = TZInfo::Timezone.new("Australia/Sydney")
Promotion.find(1).attributes["valid_from"]
Promotion.find(1).save!
Promotion.find(1).attributes["valid_from"]
p = Promotion.find(1)
p.valid_from
p.save!
Promotion.find(1).attributes["valid_from"]
Promotion.find(1).save!
Promotion.find(1).attributes["valid_from"]
Promotion.find(1).save!
Promotion.find(1).attributes["valid_from"]
Promotion.find(1).save!
Promotion.find(1).attributes["valid_from"]
This problem pops its head up in an action such as this:
class PromotionsController < ApplicationController
def publish
promotion = Promotion.find(params[:id])
promotion.update_attributes!(:published, true)
redirect_to promotion
end
end
Attached is a failing test case, as well as patch which fixes things by using an attr_writer rather than a before_validation callback.