schema_plus_pg_types 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/adapter.rb +3 -1
- data/lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/column_methods.rb +3 -6
- data/lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/schema_statements.rb +9 -6
- data/lib/schema_plus/pg_types/version.rb +1 -1
- data/spec/conversion_spec.rb +104 -0
- data/spec/migration_spec.rb +42 -62
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0197b125994ba886389559a240f881d856818f7a
|
4
|
+
data.tar.gz: 9c47a6c798a6f031c48622016a96f8883420a02b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4cb6dc33e28c527cdadbe55841e5cd52ed5e4e4195ab6e86ec38c502b03dda11306a521178ea2ecef9f13f29f7a0b580232dfb24d29d12ef2ffd080fe1d7d4c
|
7
|
+
data.tar.gz: 4ec366d08c9cbbf581865bf6b47b005054ce42ce2a2e1c793fca622948c50b035b2a7eed71d228ee1bb319967dc0b697d54cbfd4356100a776198c4e20f86376
|
data/README.md
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
require 'active_record/connection_adapters/postgresql_adapter'
|
2
2
|
require_relative 'oid/interval'
|
3
|
+
require_relative 'schema_statements'
|
3
4
|
|
4
5
|
module SchemaPlus::PgTypes
|
5
6
|
module ActiveRecord
|
6
7
|
module ConnectionAdapters
|
7
8
|
module PostgreSQLAdapter
|
9
|
+
include PostgreSQL::SchemaStatements
|
10
|
+
|
8
11
|
def configure_connection
|
9
12
|
super
|
10
13
|
|
11
|
-
|
12
14
|
# Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
|
13
15
|
execute('SET intervalstyle = iso_8601', 'SCHEMA')
|
14
16
|
end
|
data/lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/column_methods.rb
CHANGED
@@ -7,16 +7,13 @@ module SchemaPlus::PgTypes
|
|
7
7
|
args.each { |name| column(name, :interval, options) }
|
8
8
|
end
|
9
9
|
end
|
10
|
+
|
10
11
|
module Table
|
11
|
-
|
12
|
-
args.each { |name| column(name, :interval, options) }
|
13
|
-
end
|
12
|
+
include ColumnMethods
|
14
13
|
end
|
15
14
|
|
16
15
|
module TableDefinition
|
17
|
-
|
18
|
-
args.each { |name| column(name, :interval, options) }
|
19
|
-
end
|
16
|
+
include ColumnMethods
|
20
17
|
end
|
21
18
|
end
|
22
19
|
end
|
data/lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/schema_statements.rb
CHANGED
@@ -5,15 +5,18 @@ module SchemaPlus::PgTypes
|
|
5
5
|
module ConnectionAdapters
|
6
6
|
module PostgreSQL
|
7
7
|
module SchemaStatements
|
8
|
-
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
8
|
+
def type_to_sql(type, limit = nil, precision = nil, scale = nil, array = nil)
|
9
9
|
case type.to_s
|
10
10
|
when 'interval'
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
sql = 'interval'
|
12
|
+
if precision
|
13
|
+
sql << case precision
|
14
|
+
when 0..6; "(#{precision})"
|
15
|
+
else raise(::ActiveRecord::ActiveRecordError, "No interval type has precision of #{precision}. The allowed range of precision is from 0 to 6")
|
16
|
+
end
|
16
17
|
end
|
18
|
+
sql << '[]' if array
|
19
|
+
sql
|
17
20
|
else
|
18
21
|
super(type, limit, precision, scale)
|
19
22
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record/schema_dumper'
|
3
|
+
|
4
|
+
class Item < ActiveRecord::Base
|
5
|
+
end
|
6
|
+
|
7
|
+
class DefaultItem < ActiveRecord::Base
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'Conversion' do
|
12
|
+
|
13
|
+
let(:migration) { ActiveRecord::Migration }
|
14
|
+
let(:connection) { ActiveRecord::Base.connection }
|
15
|
+
let(:schema) { ActiveRecord::Schema }
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
define_schema
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'INTERVAL data type' do
|
22
|
+
TEST_DURATIONS = [
|
23
|
+
0.seconds,
|
24
|
+
0.days,
|
25
|
+
0.years,
|
26
|
+
27.seconds,
|
27
|
+
28.minutes,
|
28
|
+
3.hours,
|
29
|
+
15.days,
|
30
|
+
3.weeks,
|
31
|
+
2.months,
|
32
|
+
1.year,
|
33
|
+
5.years,
|
34
|
+
5.years + 7.months + 10.days + 6.hours + 7.minutes + 8.seconds
|
35
|
+
]
|
36
|
+
|
37
|
+
it 'should convert numeric values to proper durations (round trip)' do
|
38
|
+
[0, 3600].each{|numeric_duration| Item.create(duration: numeric_duration)}
|
39
|
+
durations = Item.pluck(:duration)
|
40
|
+
expect(durations).to all(be_an(ActiveSupport::Duration))
|
41
|
+
expect(durations).to eq([0.seconds, 1.hour])
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should convert data from ActiveSupport::Duration (round trip)' do
|
45
|
+
TEST_DURATIONS.each{|duration| Item.create(duration: duration)}
|
46
|
+
durations = Item.pluck(:duration)
|
47
|
+
expect(durations).to all(be_an(ActiveSupport::Duration))
|
48
|
+
expect(durations).to eq(TEST_DURATIONS)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should convert data to ActiveSupport::Duration' do
|
52
|
+
connection.execute(<<~EOF
|
53
|
+
INSERT INTO items (duration)
|
54
|
+
VALUES
|
55
|
+
('0 seconds'),
|
56
|
+
('0'),
|
57
|
+
('0 years'),
|
58
|
+
('27 seconds'),
|
59
|
+
('28 minutes'),
|
60
|
+
('3 hours'),
|
61
|
+
('15 days'),
|
62
|
+
('3 weeks'),
|
63
|
+
('2 months'),
|
64
|
+
('1 year'),
|
65
|
+
('5 years'),
|
66
|
+
('5 years 7 months 10 days 6 hours 7 minutes 8 seconds');
|
67
|
+
EOF
|
68
|
+
)
|
69
|
+
durations = Item.pluck(:duration)
|
70
|
+
expect(durations).to all(be_an(ActiveSupport::Duration))
|
71
|
+
expect(durations).to eq(TEST_DURATIONS)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should support default values' do
|
75
|
+
DefaultItem.create
|
76
|
+
item_with_default_value = DefaultItem.first
|
77
|
+
expect(item_with_default_value.duration).to be_an(ActiveSupport::Duration)
|
78
|
+
expect(item_with_default_value.duration).to eq(2.years + 5.minutes)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should properly dump the schema' do
|
82
|
+
stream = StringIO.new
|
83
|
+
ActiveRecord::SchemaDumper.dump(connection, stream)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def define_schema
|
91
|
+
connection.data_sources.each do |table| connection.drop_table table, cascade: true end
|
92
|
+
|
93
|
+
schema.define do
|
94
|
+
|
95
|
+
create_table :items, force: true do |t|
|
96
|
+
t.interval :duration
|
97
|
+
end
|
98
|
+
|
99
|
+
create_table :default_items, force: true do |t|
|
100
|
+
t.interval :duration, default: 2.years + 5.minutes
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/spec/migration_spec.rb
CHANGED
@@ -15,83 +15,63 @@ describe 'Migration' do
|
|
15
15
|
let(:schema) { ActiveRecord::Schema }
|
16
16
|
|
17
17
|
before(:each) do
|
18
|
-
|
18
|
+
clear_tables
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'INTERVAL data type' do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
3.hours,
|
29
|
-
15.days,
|
30
|
-
3.weeks,
|
31
|
-
2.months,
|
32
|
-
1.year,
|
33
|
-
5.years,
|
34
|
-
5.years + 7.months + 10.days + 6.hours + 7.minutes + 8.seconds
|
35
|
-
]
|
36
|
-
|
37
|
-
it 'should convert data from ActiveSupport::Duration (round trip)' do
|
38
|
-
TEST_DURATIONS.each{|duration| Item.create(duration: duration)}
|
39
|
-
durations = Item.pluck(:duration)
|
40
|
-
expect(durations).to all(be_an(ActiveSupport::Duration))
|
41
|
-
expect(durations).to eq(TEST_DURATIONS)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'should convert data to ActiveSupport::Duration' do
|
45
|
-
connection.execute(<<~EOF
|
46
|
-
INSERT INTO items (duration)
|
47
|
-
VALUES
|
48
|
-
('0 seconds'),
|
49
|
-
('0'),
|
50
|
-
('0 years'),
|
51
|
-
('27 seconds'),
|
52
|
-
('28 minutes'),
|
53
|
-
('3 hours'),
|
54
|
-
('15 days'),
|
55
|
-
('3 weeks'),
|
56
|
-
('2 months'),
|
57
|
-
('1 year'),
|
58
|
-
('5 years'),
|
59
|
-
('5 years 7 months 10 days 6 hours 7 minutes 8 seconds');
|
60
|
-
EOF
|
61
|
-
)
|
62
|
-
durations = Item.pluck(:duration)
|
63
|
-
expect(durations).to all(be_an(ActiveSupport::Duration))
|
64
|
-
expect(durations).to eq(TEST_DURATIONS)
|
22
|
+
it 'supports interval type' do
|
23
|
+
sql = create_table_sql :items do |t|
|
24
|
+
t.interval :duration
|
25
|
+
t.integer :another_field
|
26
|
+
end
|
27
|
+
expect(sql).to match /"duration" interval/
|
65
28
|
end
|
66
29
|
|
67
|
-
it '
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
expect(
|
30
|
+
it 'supports interval type with precision and array' do
|
31
|
+
sql = create_table_sql :items do |t|
|
32
|
+
t.interval :duration, precision: 5, array: true
|
33
|
+
end
|
34
|
+
expect(sql).to match /"duration" interval\(5\)\[\]/
|
72
35
|
end
|
73
36
|
|
74
|
-
it '
|
75
|
-
|
76
|
-
|
37
|
+
it 'fails when precision is too high' do
|
38
|
+
expect do
|
39
|
+
create_table_sql :items do |t|
|
40
|
+
t.interval :duration, precision: 10
|
41
|
+
end
|
42
|
+
end.to raise_error /No interval type has precision of 10/
|
77
43
|
end
|
78
|
-
|
79
44
|
end
|
80
45
|
|
81
46
|
protected
|
82
47
|
|
83
|
-
def
|
48
|
+
def clear_tables
|
84
49
|
connection.data_sources.each do |table| connection.drop_table table, cascade: true end
|
50
|
+
end
|
85
51
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
52
|
+
class DummyConnectionAdapter < ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
53
|
+
attr_reader :sql
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
@connection = nil
|
57
|
+
@owner = nil
|
58
|
+
@instrumenter = ActiveSupport::Notifications.instrumenter
|
59
|
+
@logger = nil
|
60
|
+
@config = {}
|
61
|
+
@pool = nil
|
62
|
+
@quoted_column_names, @quoted_table_names = {}, {}
|
63
|
+
@visitor = arel_visitor
|
64
|
+
@sql = []
|
65
|
+
end
|
91
66
|
|
92
|
-
|
93
|
-
|
94
|
-
end
|
67
|
+
def execute(sql)
|
68
|
+
@sql << sql
|
95
69
|
end
|
96
70
|
end
|
71
|
+
|
72
|
+
def create_table_sql(*args, **opts, &block)
|
73
|
+
conn = DummyConnectionAdapter.new
|
74
|
+
conn.create_table *args, **opts, &block
|
75
|
+
conn.sql.join '; '
|
76
|
+
end
|
97
77
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_plus_pg_types
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Yaniv
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -156,6 +156,7 @@ files:
|
|
156
156
|
- migration_spec.rb
|
157
157
|
- schema_dev.yml
|
158
158
|
- schema_plus_pg_types.gemspec
|
159
|
+
- spec/conversion_spec.rb
|
159
160
|
- spec/migration_spec.rb
|
160
161
|
- spec/sanity_spec.rb
|
161
162
|
- spec/spec_helper.rb
|
@@ -184,6 +185,7 @@ signing_key:
|
|
184
185
|
specification_version: 4
|
185
186
|
summary: Adds supports for PostgreSQL types that were left out by Rails
|
186
187
|
test_files:
|
188
|
+
- spec/conversion_spec.rb
|
187
189
|
- spec/migration_spec.rb
|
188
190
|
- spec/sanity_spec.rb
|
189
191
|
- spec/spec_helper.rb
|