schema_plus_pg_types 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|