Skip to content

Commit ab22747

Browse files
author
Yorick Peterse
committed
Merge branch 'mk-add-datetime-with-timezone-table-definition' into 'master'
Add `datetime_with_timezone` to table definition See merge request !12292
2 parents 6e66473 + ec7b3a8 commit ab22747

File tree

2 files changed

+81
-14
lines changed

2 files changed

+81
-14
lines changed

config/initializers/active_record_data_types.rb

+65-8
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,78 @@
44
if Gitlab::Database.postgresql?
55
require 'active_record/connection_adapters/postgresql_adapter'
66

7-
module ActiveRecord
8-
module ConnectionAdapters
9-
class PostgreSQLAdapter
10-
NATIVE_DATABASE_TYPES.merge!(datetime_with_timezone: { name: 'timestamptz' })
7+
module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
8+
# Add the class `DateTimeWithTimeZone` so we can map `timestamptz` to it.
9+
class DateTimeWithTimeZone < DateTime
10+
def type
11+
:datetime_with_timezone
1112
end
1213
end
1314
end
15+
16+
module RegisterDateTimeWithTimeZone
17+
# Run original `initialize_type_map` and then register `timestamptz` as a
18+
# `DateTimeWithTimeZone`.
19+
#
20+
# Apparently it does not matter that the original `initialize_type_map`
21+
# aliases `timestamptz` to `timestamp`.
22+
#
23+
# When schema dumping, `timestamptz` columns will be output as
24+
# `t.datetime_with_timezone`.
25+
def initialize_type_map(mapping)
26+
super mapping
27+
28+
mapping.register_type 'timestamptz' do |_, _, sql_type|
29+
precision = extract_precision(sql_type)
30+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone.new(precision: precision)
31+
end
32+
end
33+
end
34+
35+
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
36+
prepend RegisterDateTimeWithTimeZone
37+
38+
# Add column type `datetime_with_timezone` so we can do this in
39+
# migrations:
40+
#
41+
# add_column(:users, :datetime_with_timezone)
42+
#
43+
NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamptz' }
44+
end
1445
elsif Gitlab::Database.mysql?
1546
require 'active_record/connection_adapters/mysql2_adapter'
1647

17-
module ActiveRecord
18-
module ConnectionAdapters
19-
class AbstractMysqlAdapter
20-
NATIVE_DATABASE_TYPES.merge!(datetime_with_timezone: { name: 'timestamp' })
48+
module RegisterDateTimeWithTimeZone
49+
# Run original `initialize_type_map` and then register `timestamp` as a
50+
# `MysqlDateTimeWithTimeZone`.
51+
#
52+
# When schema dumping, `timestamp` columns will be output as
53+
# `t.datetime_with_timezone`.
54+
def initialize_type_map(mapping)
55+
super mapping
56+
57+
mapping.register_type(%r(timestamp)i) do |sql_type|
58+
precision = extract_precision(sql_type)
59+
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlDateTimeWithTimeZone.new(precision: precision)
2160
end
2261
end
2362
end
63+
64+
class ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter
65+
prepend RegisterDateTimeWithTimeZone
66+
67+
# Add the class `DateTimeWithTimeZone` so we can map `timestamp` to it.
68+
class MysqlDateTimeWithTimeZone < MysqlDateTime
69+
def type
70+
:datetime_with_timezone
71+
end
72+
end
73+
74+
# Add column type `datetime_with_timezone` so we can do this in
75+
# migrations:
76+
#
77+
# add_column(:users, :datetime_with_timezone)
78+
#
79+
NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamp' }
80+
end
2481
end

config/initializers/active_record_table_definition.rb

+16-6
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,32 @@
33

44
require 'active_record/connection_adapters/abstract/schema_definitions'
55

6-
# Appends columns `created_at` and `updated_at` to a table.
7-
#
8-
# It is used in table creation like:
9-
# create_table 'users' do |t|
10-
# t.timestamps_with_timezone
11-
# end
126
module ActiveRecord
137
module ConnectionAdapters
148
class TableDefinition
9+
# Appends columns `created_at` and `updated_at` to a table.
10+
#
11+
# It is used in table creation like:
12+
# create_table 'users' do |t|
13+
# t.timestamps_with_timezone
14+
# end
1515
def timestamps_with_timezone(**options)
1616
options[:null] = false if options[:null].nil?
1717

1818
[:created_at, :updated_at].each do |column_name|
1919
column(column_name, :datetime_with_timezone, options)
2020
end
2121
end
22+
23+
# Adds specified column with appropriate timestamp type
24+
#
25+
# It is used in table creation like:
26+
# create_table 'users' do |t|
27+
# t.datetime_with_timezone :did_something_at
28+
# end
29+
def datetime_with_timezone(column_name, **options)
30+
column(column_name, :datetime_with_timezone, options)
31+
end
2232
end
2333
end
2434
end

0 commit comments

Comments
 (0)