Last active
March 25, 2019 20:04
-
-
Save Fedcomp/f63dc6cdb5ca204c2f02302553457771 to your computer and use it in GitHub Desktop.
Rails timestamptz migration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
docker-compose --run --rm ruby test.rb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
version: '3' | |
services: | |
ruby: | |
image: ruby:2.3 | |
depends_on: | |
- db | |
working_dir: /opt/project | |
environment: | |
- TZ=Europe/Moscow | |
volumes: | |
- .:/opt/project | |
- ./volumes/ruby/bundle:/usr/local/bundle | |
command: ruby test.rb | |
db: | |
image: postgres:9.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
begin | |
require 'bundler/inline' | |
rescue LoadError => e | |
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' | |
raise e | |
end | |
gemfile(true) do | |
source 'https://rubygems.org' | |
gem 'rails', '~> 5.0', '>= 5.0.6' | |
gem 'pg' | |
gem 'rspec' | |
gem 'pry-byebug' | |
end | |
require 'logger' | |
require 'pry-byebug' | |
require 'rails/all' | |
require 'active_record' | |
require 'rspec' | |
require 'rspec/autorun' | |
DATABASE_TIMEZONE = 'UTC' # Works without migrations this way | |
# DATABASE_TIMEZONE = 'Europe/Moscow' | |
ActiveRecord::Base.logger = Logger.new(STDOUT) | |
ActiveRecord::Base.establish_connection( | |
adapter: 'postgresql', | |
user: 'postgres', | |
database: 'postgres', | |
host: 'db', | |
pool: 1 | |
) | |
binding.pry | |
# Do it before the fixing migration | |
ActiveRecord::Base.connection.execute("SET TIME ZONE '#{DATABASE_TIMEZONE}'") | |
ActiveRecord::Schema.define do | |
create_table :assignments, force: true do |t| | |
t.column :assigned_at, 'timestamp with time zone' | |
end | |
end | |
class Assignment < ActiveRecord::Base | |
end | |
OLD_ASSIGNMENT_CURRENT_TIME = Time.parse('2000-06-11 10:05:05 +0300').utc | |
NEW_ASSIGNMENT_CURRENT_TIME = Time.parse('2019-03-11 10:05:05 +0300').utc | |
TEST_OLD_ASSIGNMENT_ID = 100001 | |
TEST_NEW_ASSIGNMENT_ID = 100000 | |
# Assigment created with time in daylight saving | |
Assignment.create(id: TEST_OLD_ASSIGNMENT_ID, assigned_at: OLD_ASSIGNMENT_CURRENT_TIME) | |
# Assignment created with time without daylight saving | |
Assignment.create(id: TEST_NEW_ASSIGNMENT_ID, assigned_at: NEW_ASSIGNMENT_CURRENT_TIME) | |
class MigrateAssignmentTimestamptz < ActiveRecord::Migration[5.2] | |
def up | |
change_column :assignments, :assigned_at, :timestamp | |
end | |
end | |
MigrateAssignmentTimestamptz.migrate(:up) | |
RSpec.describe Assignment do | |
let(:current_time) { Time.parse('2019-03-11 10:05:05 +0300').utc } | |
around do |example| | |
# Database reset | |
Assignment.transaction do | |
example.call | |
raise ActiveRecord::Rollback | |
end | |
end | |
before do | |
db_timezone = ActiveRecord::Base.connection.execute('SHOW TIMEZONE').first.dig('TimeZone') | |
expect(db_timezone).to eq(DATABASE_TIMEZONE) | |
end | |
specify 'migration should fix existing old rows to have correct time' do | |
assignment = Assignment.find(TEST_OLD_ASSIGNMENT_ID) | |
expect(assignment.reload.assigned_at).to eq(OLD_ASSIGNMENT_CURRENT_TIME) | |
end | |
specify 'migration should fix existing fresh rows to have correct time' do | |
assignment = Assignment.find(TEST_NEW_ASSIGNMENT_ID) | |
expect(assignment.reload.assigned_at).to eq(NEW_ASSIGNMENT_CURRENT_TIME) | |
end | |
it 'keeps timezone between saving and reading' do | |
assignment = Assignment.create(assigned_at: current_time) | |
expect(assignment.reload.assigned_at).to eq(current_time) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment