statesman-trigger 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/README.md +72 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/rspec +16 -0
- data/bin/setup +7 -0
- data/lib/statesman-trigger.rb +1 -0
- data/lib/statesman/trigger.rb +23 -0
- data/lib/statesman/trigger/abstract_query.rb +43 -0
- data/lib/statesman/trigger/integration.rb +35 -0
- data/lib/statesman/trigger/migrations.rb +71 -0
- data/lib/statesman/trigger/null_object.rb +19 -0
- data/lib/statesman/trigger/parameters.rb +106 -0
- data/lib/statesman/trigger/trigger_query.rb +15 -0
- data/lib/statesman/trigger/update_function_query.rb +19 -0
- data/lib/statesman/trigger/version.rb +5 -0
- data/statesman-trigger.gemspec +34 -0
- metadata +232 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f9ae2e9640d93d968e583f6ed5dcf8c80a4f85ff
|
4
|
+
data.tar.gz: 5796a36556bad99d890174522ed94ca295161a99
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0fb83a8b14e76e37c475d7141efb317487472f2e02f296cd32ab81bb6c7cb25ab2d5e051ceb8d4ea4635ac4c836cc74320da8bf6dc2d9f9d63bfdf52d6752f97
|
7
|
+
data.tar.gz: 550682de13db79df2da3b08fce45e810f9dd27f764c29bdb77ff03a71ada73ac45caaa95c9e7c8d6b5c0946b97d20282f2eb9f6f2541de7462d277148ac978e7
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Statesman::Trigger
|
2
|
+
|
3
|
+
This is an extension to the fantastic [Statesman gem](https://github.com/gocardless/statesman)
|
4
|
+
to create a database trigger to keep the most recent transition in sync on a specific column
|
5
|
+
on the parent model.
|
6
|
+
|
7
|
+
Presently, it is only designed to work with PostgreSQL.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'statesman-trigger'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install statesman-trigger
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Usage in a rails migration is straightforward, assuming you use the defaults:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
def change
|
31
|
+
add_column :orders, :current_state, :string, null: false, default: 'pending', index: true
|
32
|
+
|
33
|
+
create_statesman_trigger Order, OrderTransition
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
The migration script will introspect from the provided classes.
|
38
|
+
|
39
|
+
If you want your column to be named something else:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
def change
|
43
|
+
add_column :orders, :anything_you_want, :string, null: false, default: 'pending', index: true
|
44
|
+
|
45
|
+
create_statesman_trigger Order, OrderTransition, sync_column: :anything_you_want
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
It is highly recommended you switch your Rails application's schema dumping format to SQL (`db/structure.sql` rather than `db/schema.rb`). That's accomplished by the following line in `config/application.rb`:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
module YourAppHere
|
53
|
+
class Application < Rails::Application
|
54
|
+
# Use SQL for dumping.
|
55
|
+
config.active_record.schema_format = :sql
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
## Development
|
61
|
+
|
62
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
63
|
+
|
64
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
65
|
+
|
66
|
+
## Contributing
|
67
|
+
|
68
|
+
1. Fork it ( https://github.com/scryptmouse/statesman-trigger/fork )
|
69
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
70
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
71
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
72
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "statesman/trigger"
|
5
|
+
require "pry"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
require_relative '../spec/db/boot.rb'
|
12
|
+
|
13
|
+
DEFAULT_PARAMS = Statesman::Trigger::Parameters.new model_klass: Article, transition_klass: ArticleTransition
|
14
|
+
|
15
|
+
Pry.start
|
data/bin/rspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rspec' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
data/bin/setup
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'statesman/trigger'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "statesman/trigger/version"
|
2
|
+
require "active_support/all"
|
3
|
+
require "active_record"
|
4
|
+
require "pg"
|
5
|
+
require "virtus"
|
6
|
+
require "dedent"
|
7
|
+
|
8
|
+
module Statesman
|
9
|
+
module Trigger
|
10
|
+
require_relative './trigger/null_object'
|
11
|
+
require_relative './trigger/parameters'
|
12
|
+
require_relative './trigger/abstract_query'
|
13
|
+
require_relative './trigger/trigger_query'
|
14
|
+
require_relative './trigger/update_function_query'
|
15
|
+
require_relative './trigger/integration'
|
16
|
+
require_relative './trigger/migrations'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveSupport.on_load :active_record do
|
21
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.include Statesman::Trigger::Integration
|
22
|
+
ActiveRecord::Migration::CommandRecorder.include Statesman::Trigger::Migrations
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
# @abstract
|
4
|
+
class AbstractQuery
|
5
|
+
include ActiveSupport::Configurable
|
6
|
+
|
7
|
+
# @!attribute [r] parameters
|
8
|
+
# @return [Statesman::Trigger::Parameters]
|
9
|
+
attr_reader :parameters
|
10
|
+
|
11
|
+
def initialize(parameters)
|
12
|
+
@parameters = parameters
|
13
|
+
end
|
14
|
+
|
15
|
+
def up
|
16
|
+
up_query % parameters.for_query
|
17
|
+
end
|
18
|
+
|
19
|
+
def down
|
20
|
+
down_query % parameters.for_query
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
def up_query
|
25
|
+
config.up_query.presence or raise 'Define up!'
|
26
|
+
end
|
27
|
+
|
28
|
+
def down_query
|
29
|
+
config.down_query.presence or raise 'Define down!'
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def up!(raw_sql)
|
34
|
+
config.up_query = raw_sql.dedent
|
35
|
+
end
|
36
|
+
|
37
|
+
def down!(raw_sql)
|
38
|
+
config.down_query = raw_sql.dedent
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
module Integration
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def create_statesman_trigger(options = {})
|
7
|
+
statesman_trigger_requires_pg!
|
8
|
+
|
9
|
+
params = Statesman::Trigger::Parameters.new options
|
10
|
+
|
11
|
+
validation_query = params.build_validation_query
|
12
|
+
|
13
|
+
raise "target column `#{params.sync_column}` not found on `#{params.model_table}`." unless select_value(validation_query)
|
14
|
+
|
15
|
+
params.build_statements(direction: :up).map do |stmt|
|
16
|
+
execute stmt
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def drop_statesman_trigger(options = {})
|
21
|
+
statesman_trigger_requires_pg!
|
22
|
+
|
23
|
+
params = Statesman::Trigger::Parameters.new options
|
24
|
+
|
25
|
+
params.build_statements(direction: :down).map do |stmt|
|
26
|
+
execute stmt
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def statesman_trigger_requires_pg!
|
31
|
+
raise 'Requires postgres' unless adapter_name =~ /postg/i
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
MATCH_STATE_NAME = proc do |args|
|
4
|
+
args.length == 1 && args.first.kind_of?(String)
|
5
|
+
end
|
6
|
+
|
7
|
+
MATCH_MODEL_AND_TRANSITION_CLASSES = proc do |args|
|
8
|
+
args.length == 2 && args.all? { |a| a.kind_of? Class }
|
9
|
+
end
|
10
|
+
|
11
|
+
MATCH_MODEL_AND_TRANSITION_TABLES = proc do |args|
|
12
|
+
args.length == 2 && args.all? { |a| a.kind_of?(String) || a.kind_of?(Symbol) }
|
13
|
+
end
|
14
|
+
|
15
|
+
MATCH_STATE_NAME_AND_CLASSES = proc do |args|
|
16
|
+
MATCH_STATE_NAME[args.take(1)] && MATCH_MODEL_AND_TRANSITION_CLASSES[args.drop(1)]
|
17
|
+
end
|
18
|
+
|
19
|
+
MATCH_STATE_NAME_AND_TABLE_NAMES = proc do |args|
|
20
|
+
MATCH_STATE_NAME[args.take(1)] && MATCH_MODEL_AND_TRANSITION_TABLES[args.drop(1)]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Integrates with CommandRecorder
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
module Migrations
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
def create_statesman_trigger(*args, &block)
|
30
|
+
record :create_statesman_trigger, build_statesman_trigger_options(args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def drop_statesman_trigger(*args, &block)
|
34
|
+
record :drop_statesman_trigger, build_statesman_trigger_options(args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def invert_create_statesman_trigger(args, &block)
|
38
|
+
[:drop_statesman_trigger, build_statesman_trigger_options(args)]
|
39
|
+
end
|
40
|
+
|
41
|
+
def invert_drop_statesman_trigger(args, &block)
|
42
|
+
[:create_statesman_trigger, build_statesman_trigger_options(args)]
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_statesman_trigger_options(args)
|
46
|
+
options = args.extract_options!
|
47
|
+
|
48
|
+
case args
|
49
|
+
when MATCH_STATE_NAME_AND_CLASSES
|
50
|
+
options[:state_name] = args.shift
|
51
|
+
options[:model_klass] = args.shift
|
52
|
+
options[:transition_klass] = args.shift
|
53
|
+
when MATCH_STATE_NAME_AND_TABLE_NAMES
|
54
|
+
options[:state_name] = args.shift
|
55
|
+
options[:model_table] = args.shift
|
56
|
+
options[:transition_table] = args.shift
|
57
|
+
when MATCH_STATE_NAME
|
58
|
+
options[:state_name] = args.shift
|
59
|
+
when MATCH_MODEL_AND_TRANSITION_TABLES
|
60
|
+
options[:model_table] = args.shift
|
61
|
+
options[:transition_table] = args.shift
|
62
|
+
when MATCH_MODEL_AND_TRANSITION_CLASSES
|
63
|
+
options[:model_klass] = args.shift
|
64
|
+
options[:transition_klass] = args.shift
|
65
|
+
end
|
66
|
+
|
67
|
+
return [options]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
class NullObject
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
def initialize(name)
|
7
|
+
@name = name
|
8
|
+
end
|
9
|
+
|
10
|
+
def inspect
|
11
|
+
%[#{self.class}(:name => :#{name})]
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method, *args, &block)
|
15
|
+
raise NoMethodError, "You must provide :#{name} that responds to :#{method}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
class Parameters
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
PREFIX_FORMAT = "sync_%<state_name>s_state_for_%<model_table>s"
|
7
|
+
|
8
|
+
attribute :state_name, String, default: "statesman"
|
9
|
+
attribute :sync_column, String, default: "current_state"
|
10
|
+
|
11
|
+
attribute :model_klass, Object, required: false, default: :default_model_klass
|
12
|
+
attribute :transition_klass, Object, required: false, default: :default_transition_klass
|
13
|
+
|
14
|
+
attribute :model_table, String, default: :default_model_table
|
15
|
+
attribute :transition_table, String, default: :default_transition_table
|
16
|
+
attribute :foreign_key_column, String, default: :default_foreign_key_column
|
17
|
+
|
18
|
+
attribute :prefix, String, default: :default_prefix
|
19
|
+
|
20
|
+
attribute :function_name, String, default: :default_function_name
|
21
|
+
attribute :trigger_name, String, default: :default_trigger_name
|
22
|
+
|
23
|
+
# @return [String]
|
24
|
+
def build_validation_query
|
25
|
+
%[SELECT TRUE from pg_attribute WHERE attrelid = '%<model_table>s'::regclass AND attname = '%<sync_column>s' AND NOT attisdropped] % { model_table: escape_string(model_table), sync_column: escape_string(sync_column) }
|
26
|
+
end
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
# @param [:up, :down] direction
|
30
|
+
# @return [<String>]
|
31
|
+
def build_statements(direction:)
|
32
|
+
stmts = []
|
33
|
+
|
34
|
+
case direction
|
35
|
+
when :up
|
36
|
+
stmts << update_function.up
|
37
|
+
stmts << trigger_statement.up
|
38
|
+
when :down
|
39
|
+
stmts << trigger_statement.down
|
40
|
+
stmts << update_function.down
|
41
|
+
end
|
42
|
+
|
43
|
+
return stmts
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_function
|
47
|
+
@update_function ||= UpdateFunctionQuery.new self
|
48
|
+
end
|
49
|
+
|
50
|
+
def trigger_statement
|
51
|
+
@trigger_statement ||= TriggerQuery.new self
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Hash]
|
55
|
+
def for_query
|
56
|
+
attributes.slice(:state_name, :sync_column,
|
57
|
+
:model_table, :transition_table,
|
58
|
+
:function_name, :trigger_name,
|
59
|
+
:foreign_key_column)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def default_model_klass
|
64
|
+
NullObject.new :model_klass
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_transition_klass
|
68
|
+
NullObject.new :transition_klass
|
69
|
+
end
|
70
|
+
|
71
|
+
def default_prefix
|
72
|
+
sprintf(PREFIX_FORMAT, state_name: state_name, model_table: model_table)
|
73
|
+
end
|
74
|
+
|
75
|
+
def default_model_table
|
76
|
+
model_klass.table_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_transition_table
|
80
|
+
transition_klass.table_name
|
81
|
+
end
|
82
|
+
|
83
|
+
def default_foreign_key_column
|
84
|
+
return "#{model_klass.model_name.singular}_id" unless model_klass.kind_of?(NullObject)
|
85
|
+
|
86
|
+
return "#{model_table.to_s.singularize}_id"
|
87
|
+
end
|
88
|
+
|
89
|
+
def default_function_name
|
90
|
+
quote_ident "#{prefix}_fn"
|
91
|
+
end
|
92
|
+
|
93
|
+
def default_trigger_name
|
94
|
+
quote_ident "#{prefix}_trigger"
|
95
|
+
end
|
96
|
+
|
97
|
+
def escape_string(value)
|
98
|
+
PG::Connection.escape_string value
|
99
|
+
end
|
100
|
+
|
101
|
+
def quote_ident(value)
|
102
|
+
PG::Connection.quote_ident value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
# @api private
|
4
|
+
class TriggerQuery < AbstractQuery
|
5
|
+
up! <<-SQL
|
6
|
+
CREATE TRIGGER %<trigger_name>s AFTER INSERT ON %<transition_table>s
|
7
|
+
FOR EACH ROW EXECUTE PROCEDURE %<function_name>s();
|
8
|
+
SQL
|
9
|
+
|
10
|
+
down! <<-SQL
|
11
|
+
DROP TRIGGER IF EXISTS %<trigger_name>s ON %<transition_table>s;
|
12
|
+
SQL
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Statesman
|
2
|
+
module Trigger
|
3
|
+
# @api private
|
4
|
+
class UpdateFunctionQuery < AbstractQuery
|
5
|
+
up! <<-SQL
|
6
|
+
CREATE OR REPLACE FUNCTION %<function_name>s() RETURNS TRIGGER AS $$
|
7
|
+
BEGIN
|
8
|
+
UPDATE %<model_table>s SET %<sync_column>s = NEW.to_state WHERE id = NEW.%<foreign_key_column>s;
|
9
|
+
RETURN NULL;
|
10
|
+
END;
|
11
|
+
$$ LANGUAGE plpgsql;
|
12
|
+
SQL
|
13
|
+
|
14
|
+
down! <<-SQL
|
15
|
+
DROP FUNCTION IF EXISTS %<function_name>s()
|
16
|
+
SQL
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -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 'statesman/trigger/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "statesman-trigger"
|
8
|
+
spec.version = Statesman::Trigger::VERSION
|
9
|
+
spec.authors = ["Alexa Grey"]
|
10
|
+
spec.email = ["devel@mouse.vc"]
|
11
|
+
|
12
|
+
spec.summary = %q{Create a database trigger that keeps the most recent Statesman state in sync.}
|
13
|
+
spec.description = %q{Create a database trigger that keeps the most recent Statesman state in sync.}
|
14
|
+
spec.homepage = "https://github.com/scryptmouse/statesman-trigger"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport", ">= 3.2"
|
22
|
+
spec.add_dependency "activerecord", ">= 3.2"
|
23
|
+
spec.add_dependency "pg"
|
24
|
+
spec.add_dependency "virtus", "~> 1.0"
|
25
|
+
spec.add_dependency "dedent"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
spec.add_development_dependency "rspec-its"
|
31
|
+
spec.add_development_dependency "pry"
|
32
|
+
spec.add_development_dependency "simplecov"
|
33
|
+
spec.add_development_dependency "database_cleaner"
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: statesman-trigger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexa Grey
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-07-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.2'
|
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'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pg
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
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: virtus
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dedent
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.9'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.9'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '10.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec-its
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: database_cleaner
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
description: Create a database trigger that keeps the most recent Statesman state
|
182
|
+
in sync.
|
183
|
+
email:
|
184
|
+
- devel@mouse.vc
|
185
|
+
executables: []
|
186
|
+
extensions: []
|
187
|
+
extra_rdoc_files: []
|
188
|
+
files:
|
189
|
+
- ".gitignore"
|
190
|
+
- ".rspec"
|
191
|
+
- ".travis.yml"
|
192
|
+
- Gemfile
|
193
|
+
- README.md
|
194
|
+
- Rakefile
|
195
|
+
- bin/console
|
196
|
+
- bin/rspec
|
197
|
+
- bin/setup
|
198
|
+
- lib/statesman-trigger.rb
|
199
|
+
- lib/statesman/trigger.rb
|
200
|
+
- lib/statesman/trigger/abstract_query.rb
|
201
|
+
- lib/statesman/trigger/integration.rb
|
202
|
+
- lib/statesman/trigger/migrations.rb
|
203
|
+
- lib/statesman/trigger/null_object.rb
|
204
|
+
- lib/statesman/trigger/parameters.rb
|
205
|
+
- lib/statesman/trigger/trigger_query.rb
|
206
|
+
- lib/statesman/trigger/update_function_query.rb
|
207
|
+
- lib/statesman/trigger/version.rb
|
208
|
+
- statesman-trigger.gemspec
|
209
|
+
homepage: https://github.com/scryptmouse/statesman-trigger
|
210
|
+
licenses: []
|
211
|
+
metadata: {}
|
212
|
+
post_install_message:
|
213
|
+
rdoc_options: []
|
214
|
+
require_paths:
|
215
|
+
- lib
|
216
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
217
|
+
requirements:
|
218
|
+
- - ">="
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
version: '0'
|
221
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
222
|
+
requirements:
|
223
|
+
- - ">="
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: '0'
|
226
|
+
requirements: []
|
227
|
+
rubyforge_project:
|
228
|
+
rubygems_version: 2.4.5
|
229
|
+
signing_key:
|
230
|
+
specification_version: 4
|
231
|
+
summary: Create a database trigger that keeps the most recent Statesman state in sync.
|
232
|
+
test_files: []
|