procedural 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +56 -0
- data/README.markdown +50 -0
- data/Rakefile +25 -0
- data/lib/procedural/adapters/postgresql_adapter.rb +49 -0
- data/lib/procedural/adapters.rb +19 -0
- data/lib/procedural/version.rb +3 -0
- data/lib/procedural.rb +37 -0
- data/procedural.gemspec +34 -0
- data/spec/adapters/postgresql_adapter_spec.rb +62 -0
- data/spec/database.yml.sample +6 -0
- data/spec/db/test_function.rb +46 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/support/migration_helpers.rb +43 -0
- data/spec/support/minitest_matchers.rb +7 -0
- data/spec/support/minitest_shared.rb +20 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d69df288d43e4cf1f62fcb82cc25bef57064e8d5
|
4
|
+
data.tar.gz: 1f155c1eed051b135bb38dd0476b41a1f6c76187
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ed9cb2aed0465fb453e865afae2bcedddce021267699fcd6d1acccc383b7a546533e30225a2d9a6f01ea78a5609b66394a3e1cfe697b79cc9da90072033d5e7b
|
7
|
+
data.tar.gz: e9bf85a221f05c18256e54d44056cb675d93815c9c29373a99e97ff0119b1ca1a831c63ff0a14c1f13e0a7276efae42ede2de683e5e24702ad8923cdc2958815
|
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in spectacles.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
platforms :jruby do
|
7
|
+
gem "activerecord-jdbcpostgresql-adapter"
|
8
|
+
end
|
9
|
+
|
10
|
+
platforms :ruby do
|
11
|
+
gem "pg"
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem 'simplecov', require: false
|
16
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
procedural (0.0.1)
|
5
|
+
activerecord (>= 3.2.0)
|
6
|
+
activesupport (>= 3.2.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (4.2.5)
|
12
|
+
activesupport (= 4.2.5)
|
13
|
+
builder (~> 3.1)
|
14
|
+
activerecord (4.2.5)
|
15
|
+
activemodel (= 4.2.5)
|
16
|
+
activesupport (= 4.2.5)
|
17
|
+
arel (~> 6.0)
|
18
|
+
activesupport (4.2.5)
|
19
|
+
i18n (~> 0.7)
|
20
|
+
json (~> 1.7, >= 1.7.7)
|
21
|
+
minitest (~> 5.1)
|
22
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
23
|
+
tzinfo (~> 1.1)
|
24
|
+
arel (6.0.3)
|
25
|
+
builder (3.2.2)
|
26
|
+
docile (1.1.5)
|
27
|
+
i18n (0.7.0)
|
28
|
+
json (1.8.3)
|
29
|
+
minitest (5.8.3)
|
30
|
+
minitest-spec-expect (2.0.0)
|
31
|
+
minitest (~> 5.0)
|
32
|
+
pg (0.18.4)
|
33
|
+
rake (10.4.2)
|
34
|
+
simplecov (0.10.0)
|
35
|
+
docile (~> 1.1.0)
|
36
|
+
json (~> 1.8)
|
37
|
+
simplecov-html (~> 0.10.0)
|
38
|
+
simplecov-html (0.10.0)
|
39
|
+
thread_safe (0.3.5)
|
40
|
+
tzinfo (1.2.2)
|
41
|
+
thread_safe (~> 0.1)
|
42
|
+
|
43
|
+
PLATFORMS
|
44
|
+
ruby
|
45
|
+
|
46
|
+
DEPENDENCIES
|
47
|
+
activerecord-jdbcpostgresql-adapter
|
48
|
+
minitest
|
49
|
+
minitest-spec-expect
|
50
|
+
pg
|
51
|
+
procedural!
|
52
|
+
rake
|
53
|
+
simplecov
|
54
|
+
|
55
|
+
BUNDLED WITH
|
56
|
+
1.10.6
|
data/README.markdown
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Procedural
|
2
|
+
|
3
|
+
Procedural adds the ability to add functions and triggers via ActiveRecord migrations.
|
4
|
+
|
5
|
+
Thanks to [Spectacles](https://github.com/liveh2o/spectacles) where I took much inspiration for the groundwork of this gem.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install procedural #=> or include it in your Gemfile
|
11
|
+
```
|
12
|
+
|
13
|
+
## Example Migration
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class AddCreatedAtTrigger < ActiveRecord::Migration
|
17
|
+
def change
|
18
|
+
create_procedure :created_at_trigger, language: 'plpgsql', returns: 'trigger', sql: <<-SQL
|
19
|
+
IF (TG_OP = 'UPDATE') THEN
|
20
|
+
NEW."created_at" := OLD."created_at";
|
21
|
+
ELSIF (TG_OP = 'INSERT') THEN
|
22
|
+
NEW."created_at" := CURRENT_TIMESTAMP;
|
23
|
+
END IF;
|
24
|
+
RETURN NEW;
|
25
|
+
SQL
|
26
|
+
|
27
|
+
create_procedure :updated_at_trigger, language: 'plpgsql', returns: 'trigger', sql: <<-SQL
|
28
|
+
NEW."updated_at" := CURRENT_TIMESTAMP;
|
29
|
+
RETURN NEW;
|
30
|
+
SQL
|
31
|
+
|
32
|
+
create_trigger :users, :users_created_at, :created_at_trigger
|
33
|
+
create_trigger :users, :users_updated_at, :updated_at_trigger
|
34
|
+
|
35
|
+
create_trigger :posts, :posts_created_at, :created_at_trigger
|
36
|
+
create_trigger :posts, :posts_updated_at, :updated_at_trigger
|
37
|
+
end
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
## License
|
42
|
+
The MIT License (MIT)
|
43
|
+
|
44
|
+
Copyright (c) 2015 Andrew Timberlake
|
45
|
+
|
46
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
47
|
+
|
48
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
49
|
+
|
50
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
namespace :test do
|
5
|
+
adapters = [ :postgresql ]
|
6
|
+
task :all => [ :procedural ] + adapters
|
7
|
+
|
8
|
+
adapters.each do |adapter|
|
9
|
+
Rake::TestTask.new(adapter) do |t|
|
10
|
+
t.libs.push "lib"
|
11
|
+
t.libs.push "spec"
|
12
|
+
t.pattern = "spec/adapters/#{t.name}*_spec.rb"
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Rake::TestTask.new(:procedural) do |t|
|
18
|
+
t.libs.push "lib"
|
19
|
+
t.libs.push "spec"
|
20
|
+
t.pattern = "spec/procedural/**/*_spec.rb"
|
21
|
+
t.verbose = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
task :default => 'test:all'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Procedural
|
3
|
+
module Adapters
|
4
|
+
module PostgreSQLAdapter
|
5
|
+
def create_procedure(*args)
|
6
|
+
options = args.extract_options!
|
7
|
+
|
8
|
+
procedure_name = args.shift
|
9
|
+
language = options.fetch(:language)
|
10
|
+
returns = options.fetch(:returns)
|
11
|
+
sql = options.fetch(:sql)
|
12
|
+
|
13
|
+
execute(<<-SQL)
|
14
|
+
CREATE OR REPLACE FUNCTION #{quote_column_name(procedure_name)}()
|
15
|
+
RETURNS #{returns}
|
16
|
+
LANGUAGE #{language}
|
17
|
+
AS $$
|
18
|
+
BEGIN
|
19
|
+
#{sql}
|
20
|
+
END
|
21
|
+
$$
|
22
|
+
SQL
|
23
|
+
end
|
24
|
+
|
25
|
+
def drop_procedure(*args)
|
26
|
+
procedure_name = args.shift
|
27
|
+
|
28
|
+
execute("DROP FUNCTION IF EXISTS #{quote_column_name(procedure_name)}()")
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_trigger(*args)
|
32
|
+
options = args.extract_options!
|
33
|
+
|
34
|
+
table_name = args.shift
|
35
|
+
trigger_name = args.shift
|
36
|
+
procedure_name = args.shift
|
37
|
+
|
38
|
+
execute("CREATE TRIGGER #{quote_column_name(trigger_name)} BEFORE INSERT OR UPDATE ON #{quote_table_name(table_name)} FOR EACH ROW EXECUTE PROCEDURE #{quote_column_name(procedure_name)}()")
|
39
|
+
end
|
40
|
+
|
41
|
+
def drop_trigger(*args)
|
42
|
+
table_name = args.shift
|
43
|
+
trigger_name = args.shift
|
44
|
+
|
45
|
+
execute("DROP TRIGGER IF EXISTS #{quote_column_name(trigger_name)} ON #{quote_table_name(table_name)}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Procedural
|
3
|
+
SUPPORTED_ADAPTERS = %w[PostgreSQL]
|
4
|
+
|
5
|
+
def self.load_adapters
|
6
|
+
SUPPORTED_ADAPTERS.each do |adapter|
|
7
|
+
adapter_class = "#{adapter}Adapter"
|
8
|
+
|
9
|
+
if ActiveRecord::ConnectionAdapters.const_defined?(adapter_class)
|
10
|
+
require "procedural/adapters/#{adapter.downcase}_adapter"
|
11
|
+
|
12
|
+
adapter = ActiveRecord::ConnectionAdapters.const_get(adapter_class)
|
13
|
+
extension = Procedural::Adapters.const_get(adapter_class)
|
14
|
+
|
15
|
+
adapter.send :prepend, extension
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/procedural.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'active_record'
|
3
|
+
require 'procedural/procedure'
|
4
|
+
require 'procedural/adapters'
|
5
|
+
|
6
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
7
|
+
alias_method(:_procedural_original_inherited, :inherited) if method_defined?(:inherited)
|
8
|
+
|
9
|
+
def self.inherited(klass)
|
10
|
+
::Procedural::load_adapters
|
11
|
+
_procedural_orig_inherited if method_defined?(:_procedural_original_inherited)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module ActiveRecord
|
16
|
+
class Migration
|
17
|
+
class CommandRecorder
|
18
|
+
def create_procedure(*args, &block)
|
19
|
+
record(:create_procedure, args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def invert_create_procedure(args)
|
23
|
+
[:drop_procedure, args[0]]
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_trigger(*args, &block)
|
27
|
+
record(:create_trigger, args, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def invert_create_trigger(args)
|
31
|
+
[:drop_trigger, args[0..1]]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Procedural.load_adapters
|
data/procedural.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "procedural/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.version = Procedural::VERSION
|
8
|
+
gem.name = "procedural"
|
9
|
+
gem.authors = ["Andrew Timberlake"]
|
10
|
+
gem.email = ["andrew@andrewtimberlake.com"]
|
11
|
+
gem.homepage = "http://github.com/andrewtimberlake/procedural"
|
12
|
+
gem.summary = %q{A way to manage functions, triggers and stored procedures with ActiveRecord}
|
13
|
+
gem.description = %q{A way to manage functions, triggers and stored procedures with ActiveRecord}
|
14
|
+
gem.license = 'MIT'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($\)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
##
|
22
|
+
# Dependencies
|
23
|
+
#
|
24
|
+
gem.required_ruby_version = ">= 2.0.0"
|
25
|
+
gem.add_dependency "activerecord", ">= 3.2.0"
|
26
|
+
gem.add_dependency "activesupport", ">= 3.2.0"
|
27
|
+
|
28
|
+
##
|
29
|
+
# Development dependencies
|
30
|
+
#
|
31
|
+
gem.add_development_dependency "rake"
|
32
|
+
gem.add_development_dependency "minitest"
|
33
|
+
gem.add_development_dependency 'minitest-spec-expect'
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Procedural
|
5
|
+
module Adapters
|
6
|
+
describe PostgreSQLAdapter do
|
7
|
+
configure_database('postgresql')
|
8
|
+
recreate_database("procedural_test")
|
9
|
+
load_schema
|
10
|
+
|
11
|
+
it_behaves_like "an adapter"
|
12
|
+
|
13
|
+
shared_base = Class.new do
|
14
|
+
extend Procedural::Adapters::PostgreSQLAdapter
|
15
|
+
def self.quote_table_name(name); name; end
|
16
|
+
def self.quote_column_name(name); name; end
|
17
|
+
def self.execute(sql); sql; end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#create_procedure" do
|
21
|
+
it "executes the CREATE OR REPLACE FUNCTION command" do
|
22
|
+
sql = shared_base.create_procedure(:created_at_trigger, language: 'plpgsql', returns: 'trigger', sql: <<-SQL)
|
23
|
+
IF (TG_OP = 'UPDATE') THEN
|
24
|
+
NEW."created_at" := OLD."created_at";
|
25
|
+
ELSIF (TG_OP = 'INSERT') THEN
|
26
|
+
NEW."created_at" := CURRENT_TIMESTAMP;
|
27
|
+
END IF;
|
28
|
+
RETURN NEW;
|
29
|
+
SQL
|
30
|
+
|
31
|
+
expect(sql).to_match(/CREATE OR REPLACE FUNCTION created_at_trigger/);
|
32
|
+
expect(sql).to_match(/IF \(TG_OP = 'UPDATE'/);
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#drop_procedure" do
|
37
|
+
it "executes the DROP FUNCITON IF EXISTS command" do
|
38
|
+
sql = shared_base.drop_procedure(:created_at_trigger)
|
39
|
+
|
40
|
+
expect(sql).to_equal("DROP FUNCTION IF EXISTS created_at_trigger()")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#create_trigger" do
|
45
|
+
it "executes the CREATE TRIGGER command" do
|
46
|
+
sql = shared_base.create_trigger(:users, :users_created_at, :created_at_trigger)
|
47
|
+
|
48
|
+
expect(sql).to_equal("CREATE TRIGGER users_created_at BEFORE INSERT OR UPDATE ON users FOR EACH ROW EXECUTE PROCEDURE created_at_trigger()")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#drop_trigger" do
|
53
|
+
it "executes the DROP TRIGGER IF EXISTS command" do
|
54
|
+
sql = shared_base.drop_trigger(:users, :users_created_at)
|
55
|
+
|
56
|
+
expect(sql).to_equal("DROP TRIGGER IF EXISTS users_created_at ON users")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Procedural::Function.create :add_account_to_index_queue,
|
2
|
+
language: :plpgsql,
|
3
|
+
returns: :trigger,
|
4
|
+
trigger: Procedural::Trigger.new(:accounts,
|
5
|
+
when: :before,
|
6
|
+
insert: true,
|
7
|
+
update: %i[company_id company_branch_id client_id store_id branch_id agent_id account_holder_id reference number active old_number old_reference case_number],
|
8
|
+
delete: nil,
|
9
|
+
truncate: nil,
|
10
|
+
for_each: :row,
|
11
|
+
when: nil,
|
12
|
+
arguments: nil
|
13
|
+
)
|
14
|
+
sql: <<-SQL
|
15
|
+
IF TG_OP = 'INSERT' THEN
|
16
|
+
INSERT INTO cascade_jobs (job_class, arguments, priority) VALUES ('Job::Accounts', JSON_BUILD_ARRAY(NEW.id)::jsonb, 0);
|
17
|
+
INSERT INTO cascade_jobs (job_class, arguments, priority) VALUES ('Job::Entities', JSON_BUILD_ARRAY(NEW.account_holder_id)::jsonb, 0);
|
18
|
+
ELSE
|
19
|
+
IF
|
20
|
+
OLD.company_id IS DISTINCT FROM NEW.company_id OR
|
21
|
+
OLD.company_branch_id IS DISTINCT FROM NEW.company_branch_id OR
|
22
|
+
OLD.client_id IS DISTINCT FROM NEW.client_id OR
|
23
|
+
OLD.store_id IS DISTINCT FROM NEW.store_id OR
|
24
|
+
OLD.branch_id IS DISTINCT FROM NEW.branch_id OR
|
25
|
+
OLD.agent_id IS DISTINCT FROM NEW.agent_id OR
|
26
|
+
OLD.account_holder_id IS DISTINCT FROM NEW.account_holder_id OR
|
27
|
+
OLD.reference IS DISTINCT FROM NEW.reference OR
|
28
|
+
OLD.number IS DISTINCT FROM NEW.number OR
|
29
|
+
OLD.active IS DISTINCT FROM NEW.active OR
|
30
|
+
OLD.old_number IS DISTINCT FROM NEW.old_number OR
|
31
|
+
OLD.old_reference IS DISTINCT FROM NEW.old_reference OR
|
32
|
+
OLD.case_number IS DISTINCT FROM NEW.case_number
|
33
|
+
THEN
|
34
|
+
INSERT INTO cascade_jobs (job_class, arguments, priority) VALUES ('Job::Accounts', JSON_BUILD_ARRAY(NEW.id)::jsonb, 0);
|
35
|
+
END IF;
|
36
|
+
|
37
|
+
IF OLD.account_holder_id IS DISTINCT FROM NEW.account_holder_id OR OLD.active IS DISTINCT FROM NEW.active THEN
|
38
|
+
IF OLD.account_holder_id IS NOT NULL THEN
|
39
|
+
INSERT INTO cascade_jobs (job_class, arguments, priority) VALUES ('Job::Entities', JSON_BUILD_ARRAY(OLD.account_holder_id)::jsonb, 0);
|
40
|
+
END IF;
|
41
|
+
INSERT INTO cascade_jobs (job_class, arguments, priority) VALUES ('Job::Entities', JSON_BUILD_ARRAY(NEW.account_holder_id)::jsonb, 0);
|
42
|
+
END IF;
|
43
|
+
END IF;
|
44
|
+
|
45
|
+
RETURN NEW;
|
46
|
+
SQL
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
add_filter "/spec"
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'bundler'
|
9
|
+
Bundler.require(:default, :development, :test)
|
10
|
+
|
11
|
+
# TODO: I shouldn't have to do this
|
12
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
13
|
+
|
14
|
+
require 'minitest/autorun'
|
15
|
+
require 'minitest/spec/expect'
|
16
|
+
require 'support/minitest_shared'
|
17
|
+
require 'support/minitest_matchers'
|
18
|
+
require 'support/migration_helpers'
|
19
|
+
|
20
|
+
ActiveRecord::Schema.verbose = false
|
21
|
+
|
22
|
+
def configure_database(adapter)
|
23
|
+
config_path = File.expand_path(File.join(__dir__, 'database.yml'))
|
24
|
+
# puts "config_path: #{config_path.inspect}"
|
25
|
+
config = YAML.load(File.read(config_path))
|
26
|
+
# puts "config[#{adapter.inspect}]: #{config[adapter.to_s].inspect}"
|
27
|
+
@database_config = config[adapter.to_s]
|
28
|
+
end
|
29
|
+
|
30
|
+
def recreate_database(database)
|
31
|
+
ActiveRecord::Base.establish_connection(@database_config)
|
32
|
+
ActiveRecord::Base.connection.drop_database(database) rescue nil
|
33
|
+
ActiveRecord::Base.connection.create_database(database)
|
34
|
+
ActiveRecord::Base.establish_connection(@database_config.merge(:database => database))
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_schema
|
38
|
+
ActiveRecord::Schema.define(:version => 1) do
|
39
|
+
create_table :users do |t|
|
40
|
+
t.string :first_name
|
41
|
+
t.string :last_name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
shared_examples_for "an adapter" do
|
5
|
+
describe "create procedure migration" do
|
6
|
+
create_procedure_migration = Class.new(ActiveRecord::Migration) do
|
7
|
+
def change
|
8
|
+
create_procedure :test_procedure, language: 'plpgsql', returns: 'text', sql: <<-SQL.strip_heredoc
|
9
|
+
RETURN "Hello World";
|
10
|
+
SQL
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "migrates up" do
|
15
|
+
create_procedure_migration.new.exec_migration(ActiveRecord::Base.connection, :up)
|
16
|
+
expect(true).to_equal(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "migrates down" do
|
20
|
+
create_procedure_migration.new.exec_migration(ActiveRecord::Base.connection, :down)
|
21
|
+
expect(true).to_equal(true) #
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "create trigger migration" do
|
26
|
+
create_procedure_migration = Class.new(ActiveRecord::Migration) do
|
27
|
+
def change
|
28
|
+
create_procedure :test_procedure, language: 'plpgsql', returns: 'trigger', sql: "RETURN NEW;"
|
29
|
+
create_trigger :users, :users_trigger, :test_procedure
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "migrates up" do
|
34
|
+
create_procedure_migration.new.exec_migration(ActiveRecord::Base.connection, :up)
|
35
|
+
expect(true).to_equal(true)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "migrates down" do
|
39
|
+
create_procedure_migration.new.exec_migration(ActiveRecord::Base.connection, :down)
|
40
|
+
expect(true).to_equal(true) #
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
|
3
|
+
MiniTest::Spec.class_eval do
|
4
|
+
def self.shared_examples
|
5
|
+
@shared_examples ||= {}
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module MiniTest::Spec::SharedExamples
|
10
|
+
def shared_examples_for(desc, &block)
|
11
|
+
MiniTest::Spec.shared_examples[desc] = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def it_behaves_like(desc, *args)
|
15
|
+
examples = MiniTest::Spec.shared_examples[desc]
|
16
|
+
instance_exec(*args, &examples)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Object.class_eval { include(MiniTest::Spec::SharedExamples) }
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: procedural
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Timberlake
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-18 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: 3.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-spec-expect
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: A way to manage functions, triggers and stored procedures with ActiveRecord
|
84
|
+
email:
|
85
|
+
- andrew@andrewtimberlake.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- Gemfile.lock
|
93
|
+
- README.markdown
|
94
|
+
- Rakefile
|
95
|
+
- lib/procedural.rb
|
96
|
+
- lib/procedural/adapters.rb
|
97
|
+
- lib/procedural/adapters/postgresql_adapter.rb
|
98
|
+
- lib/procedural/version.rb
|
99
|
+
- procedural.gemspec
|
100
|
+
- spec/adapters/postgresql_adapter_spec.rb
|
101
|
+
- spec/database.yml.sample
|
102
|
+
- spec/db/test_function.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
- spec/support/migration_helpers.rb
|
105
|
+
- spec/support/minitest_matchers.rb
|
106
|
+
- spec/support/minitest_shared.rb
|
107
|
+
homepage: http://github.com/andrewtimberlake/procedural
|
108
|
+
licenses:
|
109
|
+
- MIT
|
110
|
+
metadata: {}
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 2.0.0
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 2.4.5.1
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: A way to manage functions, triggers and stored procedures with ActiveRecord
|
131
|
+
test_files:
|
132
|
+
- spec/adapters/postgresql_adapter_spec.rb
|
133
|
+
- spec/database.yml.sample
|
134
|
+
- spec/db/test_function.rb
|
135
|
+
- spec/spec_helper.rb
|
136
|
+
- spec/support/migration_helpers.rb
|
137
|
+
- spec/support/minitest_matchers.rb
|
138
|
+
- spec/support/minitest_shared.rb
|