schema_plus_default_expr 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: 233c5f272e73d93ee11a5689c290511864c4e613
4
+ data.tar.gz: b5989731ef1ccb2cd48b8d3e75c591d2bb3a57ec
5
+ SHA512:
6
+ metadata.gz: 37137a6e9c15d2873bcd7b2fc0b37c1e13e9d3efe7838c520d1f3f748e417015fd026c2cf650ea117c9aa7c9a17c48319de9eb66dd38da8328dea40b171b968a
7
+ data.tar.gz: 5dc9dc12ca8166865a7867220ac324e48eabc81d0c9ef873934a900ad0a15646f5610dfab46ac6d134c83891c235ebb574fa968e6cae83ea5f853f967ad6d642
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/.travis.yml ADDED
@@ -0,0 +1,17 @@
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.1.5
9
+ gemfile:
10
+ - gemfiles/activerecord-4.2/Gemfile.postgresql
11
+ - gemfiles/activerecord-4.2/Gemfile.sqlite3
12
+ env: POSTGRESQL_DB_USER=postgres
13
+ addons:
14
+ postgresql: '9.3'
15
+ before_script: bundle exec rake create_databases
16
+ after_script: bundle exec rake drop_databases
17
+ 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) 2015 ronen barzel
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,118 @@
1
+ [![Gem Version](https://badge.fury.io/rb/schema_plus_default_expr.svg)](http://badge.fury.io/rb/schema_plus_default_expr)
2
+ [![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_plus_default_expr.svg)](http://travis-ci.org/SchemaPlus/schema_plus_default_expr)
3
+ [![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_plus_default_expr.svg)](https://coveralls.io/r/SchemaPlus/schema_plus_default_expr)
4
+ [![Dependency Status](https://gemnasium.com/lomba/schema_plus_default_expr.svg)](https://gemnasium.com/SchemaPlus/schema_plus_default_expr)
5
+
6
+ # SchemaPlus::DefaultExpr
7
+
8
+ SchemaPlus::DefaultExpr extends ActiveRecord's migrations to allow you to set the default value of a column to an SQL expression.
9
+
10
+ This gem works with PostgreSQL and Sqlite3, but not MySQL; see [Compatibility](#compatibility)below.
11
+
12
+ SchemaPlus::DefaultExpr is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord extension gems.
13
+
14
+ ## Installation
15
+
16
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - begin -->
17
+ <!-- These lines are auto-inserted from a schema_dev template -->
18
+ As usual:
19
+
20
+ ```ruby
21
+ gem "schema_plus_default_expr" # in a Gemfile
22
+ gem.add_dependency "schema_plus_default_expr" # in a .gemspec
23
+ ```
24
+
25
+ <!-- SCHEMA_DEV: TEMPLATE INSTALLATION - end -->
26
+
27
+ ## <a name="compatibility"></a>Compatibility
28
+
29
+ SchemaPlus::DefaultExpr 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.1.5** with activerecord **4.2**, using **sqlite3** and **postgresql**
34
+
35
+ <!-- SCHEMA_DEV: MATRIX - end -->
36
+
37
+ MySQL only supports SQL expression defaults for `TIMESTAMP` column types, which ActiveRecord does not use. So SchemaPlus::DefaultExpr does not work with MySQL.
38
+
39
+ ## Usage
40
+
41
+ SchemaPlus::DefaultExpr augments the syntax for setting column defaults, to support expressions or constant values:
42
+
43
+ t.datetime :seen_at, default: { expr: 'NOW()' }
44
+ t.datetime :seen_at, default: { value: "2011-12-11 00:00:00" }
45
+
46
+ The standard syntax will still work as usual:
47
+
48
+ t.datetime :seen_at, default: "2011-12-11 00:00:00"
49
+
50
+ Also, as a convenience
51
+
52
+ t.datetime :seen_at, default: :now
53
+
54
+ resolves to:
55
+
56
+ NOW() # PostgreSQL
57
+ (DATETIME('now')) # SQLite3
58
+ invalid # MySQL
59
+
60
+ ### Note on PostgreSQL & json:
61
+
62
+ If you are using Postgresql with a `json` column, ActiveRecord allows you to use a Hash for a default value. Be aware that if the hash contains just one key which is `:expr` or `:value`, then SchemaPlus::DefaultExpr will interpret, and use the corresponding value for the default. That is, these are equivalent:
63
+
64
+ t.json :fields, default: { value: { field1: 'a', field2: 'b' } }
65
+ t.json :fields, default: { field1: 'a', field2: 'b' }
66
+
67
+
68
+ ## History
69
+
70
+ * 0.1.0 - Initial release, extracted from schema_plus 1.x
71
+
72
+ ## Development & Testing
73
+
74
+ Are you interested in contributing to SchemaPlus::DefaultExpr? Thanks! Please follow
75
+ the standard protocol: fork, feature branch, develop, push, and issue pull
76
+ request.
77
+
78
+ Some things to know about to help you develop and test:
79
+
80
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
81
+ <!-- These lines are auto-inserted from a schema_dev template -->
82
+ * **schema_dev**: SchemaPlus::DefaultExpr uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
83
+ facilitate running rspec tests on the matrix of ruby, activerecord, and database
84
+ versions that the gem supports, both locally and on
85
+ [travis-ci](http://travis-ci.org/SchemaPlus/schema_plus_default_expr)
86
+
87
+ To to run rspec locally on the full matrix, do:
88
+
89
+ $ schema_dev bundle install
90
+ $ schema_dev rspec
91
+
92
+ 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.
93
+
94
+ The matrix of configurations is specified in `schema_dev.yml` in
95
+ the project root.
96
+
97
+
98
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
99
+
100
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
101
+ <!-- These lines are auto-inserted from a schema_dev template -->
102
+ * **schema_plus_core**: SchemaPlus::DefaultExpr uses the SchemaPlus::Core API that
103
+ provides middleware callback stacks to make it easy to extend
104
+ ActiveRecord's behavior. If that API is missing something you need for
105
+ your contribution, please head over to
106
+ [schema_plus_core](https://github.com/SchemaPlus/schema_plus_core) and open
107
+ an issue or pull request.
108
+
109
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - end -->
110
+
111
+ <!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - begin -->
112
+ <!-- These lines are auto-inserted from a schema_dev template -->
113
+ * **schema_monkey**: SchemaPlus::DefaultExpr is implemented as a
114
+ [schema_monkey](https://github.com/SchemaPlus/schema_monkey) client,
115
+ using [schema_monkey](https://github.com/SchemaPlus/schema_monkey)'s
116
+ convention-based protocols for extending ActiveRecord and using middleware stacks.
117
+
118
+ <!-- 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", "~> 4.2.0"
@@ -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,10 @@
1
+ require "pathname"
2
+ eval(Pathname.new(__FILE__).dirname.join("Gemfile.base").read, binding)
3
+
4
+ platform :ruby do
5
+ gem "sqlite3"
6
+ end
7
+
8
+ platform :jruby do
9
+ gem 'activerecord-jdbcsqlite3-adapter', '>=1.3.0.beta2'
10
+ end
@@ -0,0 +1,13 @@
1
+ module SchemaPlus::DefaultExpr
2
+ module ActiveRecord
3
+ module ConnectionAdapters
4
+ module AbstractAdapter
5
+ def sql_for_function(function)
6
+ # Default nil implementation to be overriden by db adapters.
7
+ # (Keep this here to avoid failure if gem is loaded with mysql2 or
8
+ # other non-supported db adapters.)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module SchemaPlus::DefaultExpr
2
+ module ActiveRecord
3
+ module ConnectionAdapters
4
+ module Column
5
+ module Sqlite3
6
+ def default_function
7
+ @default_function ||= "(#{default})" if default =~ /DATETIME/
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module SchemaPlus::DefaultExpr
2
+ module ActiveRecord
3
+ module ConnectionAdapters
4
+ module PostgresqlAdapter
5
+ def default_expr_valid?(expr)
6
+ true # arbitrary sql is okay in PostgreSQL
7
+ end
8
+
9
+ def sql_for_function(function)
10
+ case function
11
+ when :now
12
+ "NOW()"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module SchemaPlus::DefaultExpr
2
+ module ActiveRecord
3
+ module ConnectionAdapters
4
+ module Sqlite3Adapter
5
+
6
+ def default_expr_valid?(expr)
7
+ true # arbitrary sql is okay
8
+ end
9
+
10
+ def sql_for_function(function)
11
+ case function
12
+ when :now
13
+ "(DATETIME('now'))"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ module SchemaPlus::DefaultExpr
2
+ module Middleware
3
+
4
+ module Sql
5
+ module ColumnOptions
6
+
7
+ # Add options for default expressions
8
+ def before(env)
9
+ options = env.options
10
+
11
+ return unless (default = options[:default])
12
+
13
+ if default.is_a? Hash and [[:expr], [:value]].include?(default.keys)
14
+ value = default[:value]
15
+ expr = env.connection.sql_for_function(default[:expr]) || default[:expr] if default[:expr]
16
+ else
17
+ value = default
18
+ expr = env.connection.sql_for_function(default)
19
+ end
20
+
21
+ if expr
22
+ raise ArgumentError, "Invalid default expression" unless env.connection.default_expr_valid?(expr)
23
+ env.sql << " DEFAULT #{expr}"
24
+ # must explicitly check for :null to allow change_column to work on migrations
25
+ if options[:null] == false
26
+ env.sql << " NOT NULL"
27
+ end
28
+ options.delete(:default)
29
+ options.delete(:null)
30
+ else
31
+ options[:default] = value
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module Dumper
38
+ module Table
39
+
40
+ # Emit default expression options in dump
41
+ def after(env)
42
+ env.connection.columns(env.table.name).each do |column|
43
+ if !column.default_function.nil?
44
+ if col = env.table.columns.find(&its.name == column.name)
45
+ options = "default: { expr: #{column.default_function.inspect} }"
46
+ options += ", #{col.options}" unless col.options.blank?
47
+ col.options = options
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ module SchemaPlus
2
+ module DefaultExpr
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require 'schema_plus/core'
2
+
3
+ require_relative 'default_expr/version'
4
+ require_relative 'default_expr/middleware'
5
+ require_relative 'default_expr/active_record/connection_adapters/abstract_adapter'
6
+ require_relative 'default_expr/active_record/connection_adapters/column'
7
+ require_relative 'default_expr/active_record/connection_adapters/postgresql_adapter'
8
+ require_relative 'default_expr/active_record/connection_adapters/sqlite3_adapter'
9
+
10
+ SchemaMonkey.register SchemaPlus::DefaultExpr
@@ -0,0 +1 @@
1
+ require_relative 'schema_plus/default_expr'
data/schema_dev.yml ADDED
@@ -0,0 +1,7 @@
1
+ ruby:
2
+ - 2.1.5
3
+ activerecord:
4
+ - 4.2
5
+ db:
6
+ - sqlite3
7
+ - 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/default_expr/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "schema_plus_default_expr"
8
+ gem.version = SchemaPlus::DefaultExpr::VERSION
9
+ gem.authors = ["ronen barzel"]
10
+ gem.email = ["ronen@barzel.org"]
11
+ gem.summary = %q{Extends ActiveRecord migrations to allow an SQL expression for the default value of a column}
12
+ gem.homepage = "https://github.com/SchemaPlus/schema_plus_default_expr"
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", "~> 4.2"
21
+ gem.add_dependency "schema_plus_core", "~> 0.2", ">= 0.2.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.4"
27
+ gem.add_development_dependency "simplecov"
28
+ gem.add_development_dependency "simplecov-gem-profile"
29
+ end
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Column definition" do
4
+ before(:each) do
5
+ define_schema do
6
+ create_table :models, :force => true do |t|
7
+ end
8
+ end
9
+ class Model < ::ActiveRecord::Base ; end
10
+ end
11
+
12
+ subject {
13
+ Model.connection.execute("INSERT INTO models (dummy) values (1)")
14
+ Model.last.reload.test_column
15
+ }
16
+
17
+ context "text columns" do
18
+
19
+ before(:each) do
20
+ @nowish = /(#{Time.now.utc.to_s.sub(/:[^:]+$/, '')}|#{Time.now.to_s.sub(/:[^:]+$/,'')}).*/
21
+ end
22
+
23
+ context "just default passed" do
24
+ before(:each) do
25
+ define_test_column(:string, :default => "2011-12-11 00:00:00")
26
+ end
27
+
28
+ it "should use the normal default" do
29
+ is_expected.to eq "2011-12-11 00:00:00"
30
+ end
31
+ end
32
+
33
+ context "just default passed in hash" do
34
+ before(:each) do
35
+ define_test_column(:string, :default => { :value => "2011-12-11 00:00:00" })
36
+ end
37
+
38
+ it "should use the normal default" do
39
+ is_expected.to eq "2011-12-11 00:00:00"
40
+ end
41
+ end
42
+
43
+ context "default passed with no nulls" do
44
+ before(:each) do
45
+ define_test_column(:string, :default => "2011-12-11 00:00:00", null: false)
46
+ end
47
+
48
+ it "should use the normal default" do
49
+ is_expected.to eq "2011-12-11 00:00:00"
50
+ end
51
+ end
52
+
53
+ context "default passed in hash with no nulls" do
54
+ before(:each) do
55
+ define_test_column(:string, :default => { :value => "2011-12-11 00:00:00" }, null: false)
56
+ end
57
+
58
+ it "should use the normal default" do
59
+ is_expected.to eq "2011-12-11 00:00:00"
60
+ end
61
+ end
62
+
63
+ context "default function passed as :now" do
64
+ before(:each) do
65
+ define_test_column(:string, :default => :now)
66
+ end
67
+
68
+ it "should use NOW() as the default" do
69
+ is_expected.to match @nowish
70
+ end
71
+ end
72
+
73
+ context "default function passed as now with no nulls" do
74
+ before(:each) do
75
+ define_test_column(:string, :default => :now, null: false)
76
+ end
77
+
78
+ it "should use NOW() as the default" do
79
+ is_expected.to match @nowish
80
+ end
81
+ end
82
+
83
+ context "valid expr passed as default" do
84
+ it "uses the expression" do
85
+ define_test_column(:string, :default => { :expr => "(replace('THIS IS A TEST', 'TEST', 'DOG'))" })
86
+ is_expected.to eq "THIS IS A DOG"
87
+ end
88
+ end
89
+
90
+ end
91
+
92
+ context "boolean column" do
93
+
94
+ context "passed as boolean false" do
95
+ before(:each) do
96
+ define_test_column :boolean, :default => false
97
+ end
98
+
99
+ it "should give the default as false" do
100
+ is_expected.to eq false
101
+ end
102
+ end
103
+
104
+ context "passed as boolean true" do
105
+ before(:each) do
106
+ define_test_column :boolean, :default => true
107
+ end
108
+
109
+ it "should give the default as true" do
110
+ is_expected.to eq true
111
+ end
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ def define_test_column(type, *args)
118
+ ActiveRecord::Migration.suppress_messages do
119
+ ActiveRecord::Migration.create_table Model.table_name, :force => true do |t|
120
+ t.send type, :test_column, *args
121
+ t.integer :dummy
122
+ end
123
+ end
124
+ Model.reset_column_information
125
+ @column = Model.columns.first()
126
+ end
127
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRecord::Migration do
4
+
5
+ before(:each) do
6
+ define_schema do
7
+ create_table :posts, :force => true do |t|
8
+ t.string :content
9
+ end
10
+ end
11
+ class Post < ::ActiveRecord::Base ; end
12
+ end
13
+
14
+ context "when table is created" do
15
+
16
+ before(:each) do
17
+ @model = Post
18
+ end
19
+
20
+ it "should properly handle default values for booleans" do
21
+ expect {
22
+ recreate_table(@model) do |t|
23
+ t.boolean :bool, :default => true
24
+ end
25
+ }.to_not raise_error
26
+ expect(@model.create.reload.bool).to be true
27
+ end
28
+
29
+ it "should properly handle default values for json (#195)", :postgresql => :only do
30
+ recreate_table(@model) do |t|
31
+ t.json :json, :default => {}
32
+ end
33
+ expect(@model.create.reload.json).to eq({})
34
+ end
35
+
36
+ end
37
+
38
+ def recreate_table(model, opts={}, &block)
39
+ ActiveRecord::Migration.suppress_messages do
40
+ ActiveRecord::Migration.create_table model.table_name, opts.merge(:force => true), &block
41
+ end
42
+ model.reset_column_information
43
+ end
44
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+
4
+ describe "Schema dump" do
5
+
6
+ before(:all) do
7
+ ActiveRecord::Migration.suppress_messages do
8
+ ActiveRecord::Schema.define do
9
+ connection.tables.each do |table| drop_table table, force: :cascade end
10
+
11
+ create_table :posts, :force => true do |t|
12
+ t.text :body
13
+ t.integer :user_id
14
+ t.integer :first_comment_id
15
+ t.string :string_no_default
16
+ t.integer :short_id
17
+ t.string :str_short
18
+ t.integer :integer_col
19
+ t.float :float_col
20
+ t.decimal :decimal_col
21
+ t.datetime :datetime_col
22
+ t.timestamp :timestamp_col
23
+ t.time :time_col
24
+ t.date :date_col
25
+ t.binary :binary_col
26
+ t.boolean :boolean_col
27
+ end
28
+
29
+ end
30
+ end
31
+ class ::Post < ActiveRecord::Base ; end
32
+ end
33
+
34
+ context "with date default", :postgresql => :only do
35
+ it "should dump the default hash expr as now()" do
36
+ with_additional_column Post, :posted_at, :datetime, :default => :now do
37
+ expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr\s*=>)\s*"now\(\)"\s*\}})
38
+ end
39
+ end
40
+
41
+ it "should dump the default hash expr as CURRENT_TIMESTAMP" do
42
+ with_additional_column Post, :posted_at, :datetime, :default => {:expr => 'date \'2001-09-28\''} do
43
+ expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>).*2001-09-28.*})
44
+ end
45
+ end
46
+
47
+ it "can dump a complex default expression" do
48
+ with_additional_column Post, :name, :string, :default => {:expr => 'substring(random()::text from 3 for 6)'} do
49
+ expect(dump_posts).to match(%r{t\.string\s+"name",\s*(?:default:|:default\s*=>)\s*{\s*(?:expr:|:expr\s*=>)\s*"\\"substring\\"\(\(random\(\)\)::text, 3, 6\)"\s*}})
50
+ end
51
+ end
52
+ end
53
+
54
+ context "with date default", :sqlite3 => :only do
55
+ it "should dump the default hash expr as now" do
56
+ with_additional_column Post, :posted_at, :datetime, :default => :now do
57
+ expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
58
+ end
59
+ end
60
+
61
+ it "should dump the default hash expr string as now" do
62
+ with_additional_column Post, :posted_at, :datetime, :default => { :expr => "(DATETIME('now'))" } do
63
+ expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
64
+ end
65
+ end
66
+
67
+ it "should dump the default value normally" do
68
+ with_additional_column Post, :posted_at, :string, :default => "now" do
69
+ expect(dump_posts).to match(%r{t\.string\s*"posted_at",\s*(?:default:|:default =>)\s*"now"})
70
+ end
71
+ end
72
+ end
73
+
74
+ it "should leave out :default when default was changed to null" do
75
+ ActiveRecord::Migration.suppress_messages do
76
+ ActiveRecord::Migration.change_column_default :posts, :string_no_default, nil
77
+ end
78
+ # mysql2 includes 'limit: 255' in the output. that's OK, just want to
79
+ # make sure the full line doesn't have 'default' in it.
80
+ expect(dump_posts).to match(%r{t\.string\s+"string_no_default"\s*(,\s*limit:\s*\d+)?$})
81
+ end
82
+
83
+ protected
84
+ def to_regexp(string)
85
+ Regexp.new(Regexp.escape(string))
86
+ end
87
+
88
+ def with_additional_column(model, column_name, column_type, options)
89
+ table_columns = model.columns.reject{|column| column.name == 'id'}
90
+ ActiveRecord::Migration.suppress_messages do
91
+ ActiveRecord::Migration.create_table model.table_name, :force => true do |t|
92
+ table_columns.each do |column|
93
+ t.column column.name, column.type, :default => column.default
94
+ end
95
+ t.column column_name, column_type, options
96
+ end
97
+ end
98
+ yield
99
+ end
100
+
101
+ def dump_schema(opts={})
102
+ stream = StringIO.new
103
+ ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore]) || []
104
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
105
+ stream.string
106
+ end
107
+
108
+ def dump_posts
109
+ dump_schema(:ignore => %w[users comments])
110
+ end
111
+
112
+ end
113
+
@@ -0,0 +1,33 @@
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_default_expr'
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
+ def define_schema(&block)
22
+ ActiveRecord::Migration.suppress_messages do
23
+ ActiveRecord::Schema.define do
24
+ connection.tables.each do |table|
25
+ drop_table table, force: :cascade
26
+ end
27
+ instance_eval &block
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+ SimpleCov.command_name "[ruby#{RUBY_VERSION}-activerecord#{::ActiveRecord.version}-#{ActiveRecord::Base.connection.adapter_name}]"
metadata ADDED
@@ -0,0 +1,191 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schema_plus_default_expr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ronen barzel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-01 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: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
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: '0.2'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.2.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '0.2'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.2.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.4'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.4'
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
+ - ronen@barzel.org
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - ".gitignore"
139
+ - ".travis.yml"
140
+ - Gemfile
141
+ - LICENSE.txt
142
+ - README.md
143
+ - Rakefile
144
+ - gemfiles/Gemfile.base
145
+ - gemfiles/activerecord-4.2/Gemfile.base
146
+ - gemfiles/activerecord-4.2/Gemfile.postgresql
147
+ - gemfiles/activerecord-4.2/Gemfile.sqlite3
148
+ - lib/schema_plus/default_expr.rb
149
+ - lib/schema_plus/default_expr/active_record/connection_adapters/abstract_adapter.rb
150
+ - lib/schema_plus/default_expr/active_record/connection_adapters/column.rb
151
+ - lib/schema_plus/default_expr/active_record/connection_adapters/postgresql_adapter.rb
152
+ - lib/schema_plus/default_expr/active_record/connection_adapters/sqlite3_adapter.rb
153
+ - lib/schema_plus/default_expr/middleware.rb
154
+ - lib/schema_plus/default_expr/version.rb
155
+ - lib/schema_plus_default_expr.rb
156
+ - schema_dev.yml
157
+ - schema_plus_default_expr.gemspec
158
+ - spec/column_default_spec.rb
159
+ - spec/migration_spec.rb
160
+ - spec/schema_dumper_spec.rb
161
+ - spec/spec_helper.rb
162
+ homepage: https://github.com/SchemaPlus/schema_plus_default_expr
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.2.2
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: Extends ActiveRecord migrations to allow an SQL expression for the default
186
+ value of a column
187
+ test_files:
188
+ - spec/column_default_spec.rb
189
+ - spec/migration_spec.rb
190
+ - spec/schema_dumper_spec.rb
191
+ - spec/spec_helper.rb