schema_plus_pg_types 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ab8c1d45e50a98115b2794690905697521819a2a
4
+ data.tar.gz: d20941350da12ca252504e923683b1809e9a7783
5
+ SHA512:
6
+ metadata.gz: c04aef0c17a5ef56363a4a5585ad893caeb6e585e0707e2175aa698df7621f99b444fba1c7143ccff5d8c4d1e81649c0bd9f4831f5a3bb48614fb70f3eb9cdae
7
+ data.tar.gz: ae033ed292e5c7d0ef043b7c7b667316b1ba3e89e362f9568686a373725f141dd448ef65789ffa683da62f062b6d05f1960ab84f861c22882736632ff4adc157
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /coverage
2
+ /tmp
3
+ /pkg
4
+ /Gemfile.local
5
+
6
+ *.lock
7
+ *.log
8
+ *.sqlite3
9
+ !gemfiles/**/*.sqlite3
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ # This file was auto-generated by the schema_dev tool, based on the data in
2
+ # ./schema_dev.yml
3
+ # Please do not edit this file; any changes will be overwritten next time
4
+ # schema_dev gets run.
5
+ ---
6
+ sudo: false
7
+ rvm:
8
+ - 2.3.1
9
+ gemfile:
10
+ - gemfiles/activerecord-5.0/Gemfile.postgresql
11
+ env: POSTGRESQL_DB_USER=postgres
12
+ addons:
13
+ postgresql: '9.4'
14
+ before_script: bundle exec rake create_databases
15
+ after_script: bundle exec rake drop_databases
16
+ script: bundle exec rake travis
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Boaz Yaniv
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ [![Gem Version](https://badge.fury.io/rb/schema_plus_pg_types.svg)](http://badge.fury.io/rb/schema_plus_pg_types)
2
+ [![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_plus_pg_types.svg)](http://travis-ci.org/SchemaPlus/schema_plus_pg_types)
3
+ [![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_plus_pg_types.svg)](https://coveralls.io/r/SchemaPlus/schema_plus_pg_types)
4
+ [![Dependency Status](https://gemnasium.com/lomba/schema_plus_pg_types.svg)](https://gemnasium.com/SchemaPlus/schema_plus_pg_types)
5
+
6
+ # SchemaPlus::PgTypes
7
+
8
+ SchemaPlus::PgTypes adds better support for PostgreSQL-specific types to
9
+ ActiveRecord, mapping them to higher-level types instead of raw strings.
10
+ Currently this only includes the PostgreSQL `interval` type, which is mapped
11
+ to `ActiveSupport::Duration`.
12
+
13
+ ## Installation
14
+
15
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - begin -->
16
+ <!-- These lines are auto-inserted from a schema_dev template -->
17
+ As usual:
18
+
19
+ ```ruby
20
+ gem "schema_plus_pg_types" # in a Gemfile
21
+ gem.add_dependency "schema_plus_pg_types" # in a .gemspec
22
+ ```
23
+
24
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - end -->
25
+
26
+
27
+ ## Compatibility
28
+
29
+ SchemaPlus::PgTypes is tested on:
30
+
31
+ <!-- SCHEMA_DEV: MATRIX - begin -->
32
+ <!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->
33
+ * ruby **2.3.1** with activerecord **5.0**, using **postgresql**
34
+
35
+ <!-- SCHEMA_DEV: MATRIX - end -->
36
+
37
+ ## Usage
38
+
39
+ This gem adds a little more syntactic sugar for defining PostgreSQL types
40
+ in your migrations. You can now simply write:
41
+
42
+ ```ruby
43
+ create_table :events do |t|
44
+ t.interval :event_duration
45
+ end
46
+ ````
47
+
48
+ Instead of:
49
+
50
+ ```ruby
51
+ create_table :events do |t|
52
+ t.column :event_duration, :interval
53
+ end
54
+ ```
55
+
56
+ The `event_duration` column will be represented as `ActiveSupport::Duration`
57
+ in your model, so you should be able to use it without the usual fuss:
58
+
59
+ ```ruby
60
+ long_events = Event.where(1.hours..10.hours)
61
+ ````
62
+
63
+ SchemaPlus::PgTypes is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord extension gems.
64
+
65
+
66
+ ## History
67
+
68
+ * 0.1.0 - Initial release
69
+
70
+ ## Development & Testing
71
+
72
+ Are you interested in contributing to SchemaPlus::PgTypes? Thanks! Please follow
73
+ the standard protocol: fork, feature branch, develop, push, and issue pull
74
+ request.
75
+
76
+ Some things to know about to help you develop and test:
77
+
78
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
79
+ <!-- These lines are auto-inserted from a schema_dev template -->
80
+ * **schema_dev**: SchemaPlus::PgTypes uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
81
+ facilitate running rspec tests on the matrix of ruby, activerecord, and database
82
+ versions that the gem supports, both locally and on
83
+ [travis-ci](http://travis-ci.org/SchemaPlus/schema_plus_pg_types)
84
+
85
+ To to run rspec locally on the full matrix, do:
86
+
87
+ $ schema_dev bundle install
88
+ $ schema_dev rspec
89
+
90
+ You can also run on just one configuration at a time; For info, see `schema_dev --help` or the [schema_dev](https://github.com/SchemaPlus/schema_dev) README.
91
+
92
+ The matrix of configurations is specified in `schema_dev.yml` in
93
+ the project root.
94
+
95
+
96
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
97
+
98
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
99
+ <!-- These lines are auto-inserted from a schema_dev template -->
100
+ * **schema_plus_core**: SchemaPlus::PgTypes uses the SchemaPlus::Core API that
101
+ provides middleware callback stacks to make it easy to extend
102
+ ActiveRecord's behavior. If that API is missing something you need for
103
+ your contribution, please head over to
104
+ [schema_plus_core](https://github.com/SchemaPlus/schema_plus_core) and open
105
+ an issue or pull request.
106
+
107
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - end -->
108
+
109
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - begin -->
110
+ <!-- These lines are auto-inserted from a schema_dev template -->
111
+ * **schema_monkey**: SchemaPlus::PgTypes is implemented as a
112
+ [schema_monkey](https://github.com/SchemaPlus/schema_monkey) client,
113
+ using [schema_monkey](https://github.com/SchemaPlus/schema_monkey)'s
114
+ convention-based protocols for extending ActiveRecord and using middleware stacks.
115
+
116
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - end -->
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'schema_dev/tasks'
5
+
6
+ task :default => :spec
7
+
8
+ require 'rspec/core/rake_task'
9
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => File.expand_path('..', __FILE__)
3
+
4
+ File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
@@ -0,0 +1,3 @@
1
+ eval File.read File.expand_path('../../Gemfile.base', __FILE__)
2
+
3
+ gem "activerecord", "~> 5.0.1"
@@ -0,0 +1,10 @@
1
+ require "pathname"
2
+ eval(Pathname.new(__FILE__).dirname.join("Gemfile.base").read, binding)
3
+
4
+ platform :ruby do
5
+ gem "pg"
6
+ end
7
+
8
+ platform :jruby do
9
+ gem 'activerecord-jdbcpostgresql-adapter'
10
+ end
@@ -0,0 +1,29 @@
1
+ require 'active_record/connection_adapters/postgresql_adapter'
2
+ require_relative 'oid/interval'
3
+
4
+ module SchemaPlus::PgTypes
5
+ module ActiveRecord
6
+ module ConnectionAdapters
7
+ module PostgreSQLAdapter
8
+ def configure_connection
9
+ super
10
+
11
+
12
+ # Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
13
+ execute('SET intervalstyle = iso_8601', 'SCHEMA')
14
+ end
15
+
16
+ def initialize_type_map(m)
17
+ super(m)
18
+ m.register_type 'interval' do |*_, sql_type|
19
+ precision = extract_precision(sql_type)
20
+ ::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Interval.new(precision: precision)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:interval] = { name: 'interval' }
29
+
@@ -0,0 +1,24 @@
1
+ module SchemaPlus::PgTypes
2
+ module ActiveRecord
3
+ module ConnectionAdapters
4
+ module PostgreSQL
5
+ module ColumnMethods
6
+ def interval(*args, **options)
7
+ args.each { |name| column(name, :interval, options) }
8
+ end
9
+ end
10
+ module Table
11
+ def interval(*args, **options)
12
+ args.each { |name| column(name, :interval, options) }
13
+ end
14
+ end
15
+
16
+ module TableDefinition
17
+ def interval(*args, **options)
18
+ args.each { |name| column(name, :interval, options) }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ require 'active_support/duration'
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module PostgreSQL
6
+ module OID # :nodoc:
7
+ class Interval < Type::Value # :nodoc:
8
+ def type
9
+ :interval
10
+ end
11
+
12
+ def cast_value(value)
13
+ case value
14
+ when ::ActiveSupport::Duration
15
+ value
16
+ when ::String
17
+ # Will raise +ActiveSupport::Duration::ISO8601Parser::ParsingError+ on string of unknown format
18
+ ::ActiveSupport::Duration.parse(value)
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ # Dump the ISO8601 date inside the schema
25
+ def type_cast_for_schema(value)
26
+ "\"#{value.iso8601}\""
27
+ end
28
+
29
+ def serialize(value)
30
+ case value
31
+ when ::ActiveSupport::Duration
32
+ value.iso8601(precision: self.precision)
33
+ when ::Numeric
34
+ # Sometimes operations on Times returns just float number of seconds so we need to handle that.
35
+ # Example: Time.current - (Time.current + 1.hour) # => -3600.000001776 (Float)
36
+ duration = ::ActiveSupport::Duration.new(value.to_i, seconds: value.to_i)
37
+ duration.iso8601(precision: self.precision)
38
+ else
39
+ super
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,27 @@
1
+ require_relative 'oid/interval'
2
+
3
+ module SchemaPlus::PgTypes
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ module PostgreSQL
7
+ module SchemaStatements
8
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
9
+ case type.to_s
10
+ when 'interval'
11
+ return super(type, limit, precision, scale) unless precision
12
+
13
+ case precision
14
+ when 0..6; "interval(#{precision})"
15
+ else raise(ActiveRecordError, "No interval type has precision of #{precision}. The allowed range of precision is from 0 to 6")
16
+ end
17
+ else
18
+ super(type, limit, precision, scale)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,46 @@
1
+ require 'active_support/duration'
2
+ require 'active_support/duration/iso8601_serializer'
3
+
4
+ class ActiveSupport::Duration
5
+ # Patch rails inconsistent handling of ISO8601 dates.
6
+ # ActiveSupport::Duration uses fixes values for date and time elements:
7
+ # 1 Year = 365.25 days, 1 Month = 30 days, 1 Day = 24 hours, etc.
8
+ # The original parse() implementation advanced the current time by the
9
+ # specified date and time elements and then subtracted the current time
10
+ # again to get the duration. This produces inconsistent results since
11
+ # actual months and years can vary in length.
12
+ # In short, without this fix, the following expression wouldn't necessarily be true:
13
+ # 2.months == ActiveSupport::Duration.parse(2.months)
14
+ def self.parse(iso8601duration)
15
+ parts = ISO8601Parser.new(iso8601duration).parse!
16
+ total_seconds = 0
17
+ parts.each do |part, value|
18
+ total_seconds += value.send part.to_sym
19
+ end
20
+ new(total_seconds, parts)
21
+ end
22
+
23
+ # Patch rails to treat zero durations
24
+ # This bug was fixed in the following commit, but is still not part of Rails 5.0
25
+ # https://github.com/rails/rails/commit/629dde297ce5e4b7614fbb0218f2593effaf7e28
26
+ class ISO8601Serializer
27
+ def serialize
28
+ parts, sign = normalize
29
+ return 'PT0S'.freeze if parts.empty?
30
+
31
+ output = 'P'
32
+ output << "#{parts[:years]}Y" if parts.key?(:years)
33
+ output << "#{parts[:months]}M" if parts.key?(:months)
34
+ output << "#{parts[:weeks]}W" if parts.key?(:weeks)
35
+ output << "#{parts[:days]}D" if parts.key?(:days)
36
+ time = ''
37
+ time << "#{parts[:hours]}H" if parts.key?(:hours)
38
+ time << "#{parts[:minutes]}M" if parts.key?(:minutes)
39
+ if parts.key?(:seconds)
40
+ time << "#{sprintf(@precision ? "%0.0#{@precision}f" : '%g', parts[:seconds])}S"
41
+ end
42
+ output << "T#{time}" if time.present?
43
+ "#{sign}#{output}"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ module SchemaPlus
2
+ module PgTypes
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ require 'schema_plus/core'
2
+
3
+ require_relative 'pg_types/active_record/connection_adapters/postgresql/adapter'
4
+ require_relative 'pg_types/active_record/connection_adapters/postgresql/schema_statements'
5
+ require_relative 'pg_types/active_record/connection_adapters/postgresql/column_methods'
6
+ require_relative 'pg_types/active_support/duration_fixes'
7
+ require_relative 'pg_types/version'
8
+
9
+ # Load any mixins to ActiveRecord modules, such as:
10
+ #
11
+ #require_relative 'pg_types/active_record/base'
12
+
13
+ # Load any middleware, such as:
14
+ #
15
+ # require_relative 'pg_types/middleware/model'
16
+
17
+ SchemaMonkey.register SchemaPlus::PgTypes
@@ -0,0 +1 @@
1
+ require_relative 'schema_plus/pg_types'
data/migration_spec.rb ADDED
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ class Item < ActiveRecord::Base
4
+ end
5
+
6
+ class AOnes < ActiveRecord::Base
7
+ end
8
+
9
+ class ABOnes < ActiveRecord::Base
10
+ end
11
+
12
+ describe "Migration" do
13
+
14
+ let(:migration) { ActiveRecord::Migration }
15
+ let(:connection) { ActiveRecord::Base.connection }
16
+ let(:schema) { ActiveRecord::Schema }
17
+
18
+ before(:each) do
19
+ define_schema_and_data
20
+ end
21
+
22
+ context "creation" do
23
+ it "should create correct views" do
24
+ expect(AOnes.all.collect(&:s)).to eq(%W[one_one one_two])
25
+ expect(ABOnes.all.collect(&:s)).to eq(%W[one_one])
26
+ end
27
+ end
28
+
29
+ context "duplicate creation" do
30
+ before(:each) do
31
+ migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=1)')
32
+ end
33
+
34
+ it "should raise an error by default" do
35
+ expect {migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)')}.to raise_error ActiveRecord::StatementInvalid
36
+ end
37
+
38
+ it "should override existing definition if :force true" do
39
+ migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :force => true)
40
+ expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
41
+ end
42
+
43
+ context "Postgres and MySQL only", :sqlite3 => :skip do
44
+ it "should override existing definition if :allow_replace is true" do
45
+ migration.create_view('dupe_me', 'SELECT * FROM items WHERE (a=2)', :allow_replace => true)
46
+ expect(connection.view_definition('dupe_me')).to match(%r{WHERE .*a.*=.*2}i)
47
+ end
48
+ end
49
+ end
50
+
51
+ context "dropping" do
52
+ it "should raise an error if the view doesn't exist" do
53
+ expect { migration.drop_view('doesnt_exist') }.to raise_error ActiveRecord::StatementInvalid
54
+ end
55
+
56
+ it "should fail silently when using if_exists option" do
57
+ expect { migration.drop_view('doesnt_exist', :if_exists => true) }.not_to raise_error
58
+ end
59
+
60
+ context "with a view that exists" do
61
+ before { migration.create_view('view_that_exists', 'SELECT * FROM items WHERE (a=1)') }
62
+
63
+ it "should succeed" do
64
+ migration.drop_view('view_that_exists')
65
+ expect(connection.views).not_to include('view_that_exists')
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "rollback" do
71
+ it "properly rolls back a create_view" do
72
+ m = Class.new ::ActiveRecord::Migration.latest_version do
73
+ define_method(:change) {
74
+ create_view :copy, "SELECT * FROM items"
75
+ }
76
+ end
77
+ m.migrate(:up)
78
+ expect(connection.views).to include("copy")
79
+ m.migrate(:down)
80
+ expect(connection.views).not_to include("copy")
81
+ end
82
+
83
+ it "raises error for drop_view" do
84
+ m = Class.new ::ActiveRecord::Migration.latest_version do
85
+ define_method(:change) {
86
+ drop_view :a_ones
87
+ }
88
+ end
89
+ expect { m.migrate(:down) }.to raise_error(::ActiveRecord::IrreversibleMigration)
90
+ end
91
+ end
92
+
93
+
94
+ protected
95
+
96
+ def define_schema_and_data
97
+ connection.views.each do |view| connection.drop_view view end
98
+ connection.tables_only.each do |table| connection.drop_table table, cascade: true end
99
+
100
+ schema.define do
101
+
102
+ create_table :items, :force => true do |t|
103
+ t.integer :a
104
+ t.integer :b
105
+ t.string :s
106
+ end
107
+
108
+ create_view :a_ones, Item.select('b, s').where(:a => 1)
109
+ create_view :ab_ones, "select s from a_ones where b = 1"
110
+ end
111
+ connection.execute "insert into items (a, b, s) values (1, 1, 'one_one')"
112
+ connection.execute "insert into items (a, b, s) values (1, 2, 'one_two')"
113
+ connection.execute "insert into items (a, b, s) values (2, 1, 'two_one')"
114
+ connection.execute "insert into items (a, b, s) values (2, 2, 'two_two')"
115
+ end
116
+ end
data/schema_dev.yml ADDED
@@ -0,0 +1,6 @@
1
+ ruby:
2
+ - 2.3.1
3
+ activerecord:
4
+ - 5.0
5
+ db:
6
+ - postgresql
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'schema_plus/pg_types/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "schema_plus_pg_types"
8
+ gem.version = SchemaPlus::PgTypes::VERSION
9
+ gem.authors = ["Boaz Yaniv"]
10
+ gem.email = ["boazyan@gmail.com"]
11
+ gem.summary = %q{Adds supports for PostgreSQL types that were left out by Rails}
12
+ gem.homepage = "https://github.com/SchemaPlus/schema_plus_pg_types"
13
+ gem.license = "MIT"
14
+
15
+ gem.files = `git ls-files -z`.split("\x0")
16
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "activerecord", "~> 5.0"
21
+ gem.add_dependency "schema_plus_core", "~> 2.0", ">= 2.0.1"
22
+
23
+ gem.add_development_dependency "bundler", "~> 1.7"
24
+ gem.add_development_dependency "rake", "~> 10.0"
25
+ gem.add_development_dependency "rspec", "~> 3.0"
26
+ gem.add_development_dependency "schema_dev", "~> 3.8"
27
+ gem.add_development_dependency "simplecov"
28
+ gem.add_development_dependency "simplecov-gem-profile"
29
+ end
@@ -0,0 +1,97 @@
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 'Migration' 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 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)
65
+ end
66
+
67
+ it 'should support default values' do
68
+ DefaultItem.create
69
+ item_with_default_value = DefaultItem.first
70
+ expect(item_with_default_value.duration).to be_an(ActiveSupport::Duration)
71
+ expect(item_with_default_value.duration).to eq(2.years + 5.minutes)
72
+ end
73
+
74
+ it 'should properly dump the schema' do
75
+ stream = StringIO.new
76
+ ActiveRecord::SchemaDumper.dump(connection, stream)
77
+ end
78
+
79
+ end
80
+
81
+ protected
82
+
83
+ def define_schema
84
+ connection.data_sources.each do |table| connection.drop_table table, cascade: true end
85
+
86
+ schema.define do
87
+
88
+ create_table :items, force: true do |t|
89
+ t.interval :duration
90
+ end
91
+
92
+ create_table :default_items, force: true do |t|
93
+ t.interval :duration, default: 2.years + 5.minutes
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ # A basic sanity check to have as a spec when first starting. Feel free to delete this
5
+ # once you've got real content.
6
+
7
+ describe "Sanity Check" do
8
+
9
+ it "database is connected" do
10
+ expect(ActiveRecord::Base).to be_connected
11
+ end
12
+
13
+ end
@@ -0,0 +1,21 @@
1
+ require 'simplecov'
2
+ require 'simplecov-gem-profile'
3
+ SimpleCov.start "gem"
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+
8
+ require 'rspec'
9
+ require 'active_record'
10
+ require 'schema_plus_pg_types'
11
+ require 'schema_dev/rspec'
12
+
13
+ SchemaDev::Rspec.setup
14
+
15
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
16
+
17
+ RSpec.configure do |config|
18
+ config.warnings = true
19
+ end
20
+
21
+ SimpleCov.command_name "[ruby#{RUBY_VERSION}-activerecord#{::ActiveRecord.version}-#{ActiveRecord::Base.connection.adapter_name}]"
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schema_plus_pg_types
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Boaz Yaniv
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: schema_plus_core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.0.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.7'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.7'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: schema_dev
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.8'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.8'
103
+ - !ruby/object:Gem::Dependency
104
+ name: simplecov
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: simplecov-gem-profile
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ description:
132
+ email:
133
+ - boazyan@gmail.com
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - ".gitignore"
139
+ - ".idea/vcs.xml"
140
+ - ".travis.yml"
141
+ - Gemfile
142
+ - LICENSE.txt
143
+ - README.md
144
+ - Rakefile
145
+ - gemfiles/Gemfile.base
146
+ - gemfiles/activerecord-5.0/Gemfile.base
147
+ - gemfiles/activerecord-5.0/Gemfile.postgresql
148
+ - lib/schema_plus/pg_types.rb
149
+ - lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/adapter.rb
150
+ - lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/column_methods.rb
151
+ - lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/oid/interval.rb
152
+ - lib/schema_plus/pg_types/active_record/connection_adapters/postgresql/schema_statements.rb
153
+ - lib/schema_plus/pg_types/active_support/duration_fixes.rb
154
+ - lib/schema_plus/pg_types/version.rb
155
+ - lib/schema_plus_pg_types.rb
156
+ - migration_spec.rb
157
+ - schema_dev.yml
158
+ - schema_plus_pg_types.gemspec
159
+ - spec/migration_spec.rb
160
+ - spec/sanity_spec.rb
161
+ - spec/spec_helper.rb
162
+ homepage: https://github.com/SchemaPlus/schema_plus_pg_types
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project:
182
+ rubygems_version: 2.5.1
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: Adds supports for PostgreSQL types that were left out by Rails
186
+ test_files:
187
+ - spec/migration_spec.rb
188
+ - spec/sanity_spec.rb
189
+ - spec/spec_helper.rb