schema_monkey 0.4.1 → 1.0.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 +4 -4
- data/README.md +16 -3
- data/lib/schema_monkey.rb +28 -33
- data/lib/schema_monkey/core_extensions.rb +23 -0
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/base.rb +4 -4
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/connection_adapters/abstract_adapter.rb +3 -3
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/connection_adapters/mysql2_adapter.rb +8 -8
- data/lib/schema_monkey/core_extensions/active_record/connection_adapters/postgresql_adapter.rb +30 -0
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/connection_adapters/schema_statements.rb +9 -10
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/connection_adapters/sqlite3_adapter.rb +8 -8
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/connection_adapters/table_definition.rb +5 -5
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/migration/command_recorder.rb +2 -2
- data/lib/schema_monkey/{active_record → core_extensions/active_record}/schema_dumper.rb +5 -5
- data/lib/schema_monkey/core_extensions/middleware.rb +62 -0
- data/lib/schema_monkey/tool.rb +43 -0
- data/lib/schema_monkey/{client.rb → tool/client.rb} +18 -12
- data/lib/schema_monkey/tool/errors.rb +4 -0
- data/lib/schema_monkey/{module.rb → tool/module.rb} +9 -2
- data/lib/schema_monkey/tool/monkey.rb +46 -0
- data/lib/schema_monkey/{rake.rb → tool/rake.rb} +1 -1
- data/lib/schema_monkey/tool/stack.rb +90 -0
- data/lib/schema_monkey/{tasks → tool/tasks}/insert.rake +0 -0
- data/lib/schema_monkey/version.rb +1 -1
- data/schema_monkey.gemspec +0 -1
- data/spec/middleware_spec.rb +95 -0
- data/spec/spec_helper.rb +6 -1
- metadata +23 -30
- data/lib/schema_monkey/active_record/connection_adapters/postgresql_adapter.rb +0 -30
- data/lib/schema_monkey/middleware.rb +0 -117
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 63717b66e73fd1bf6bd109a53e4a9923e47067b2
|
|
4
|
+
data.tar.gz: 86c7b56f67c7b9c54a816e90f6e4309e1d766e20
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0146db8b1769a7b59f797bae5960c003f6cf59296681d381af3356e2f1c6d7e4dbe9223e36167dff098e1a0c2846131655a87f2ad5780cae0b5a0c4c8ae355ce
|
|
7
|
+
data.tar.gz: 140723e774bd68a0356bd64d041eaa8035c535f06b3ded87bbd2d642be72899f09a7babaefbdb449c5c2e35b225bbe5313fcb225b7169f5fa67e1dd4c0d1efc6
|
data/README.md
CHANGED
|
@@ -11,7 +11,6 @@ SchemaMonkey is a behind-the-scenes gem to facilitate writing extensions to Acti
|
|
|
11
11
|
|
|
12
12
|
* A convention-based protocol for `include`'ing custom modules into ActiveRecord. You just define your modules and SchemaMonkey will automatically include them in the right places.
|
|
13
13
|
|
|
14
|
-
* (If you're using Rails) It takes care of setting up a Railtie appropriately to invoke the extensions.
|
|
15
14
|
|
|
16
15
|
The middleware interface has two benefits: it provides a clean API so that the gem or aplication code doesn't need to monkey-patch ActiveRecord (SchemaMonkey does all the monkey-patching for you), and it lets multiple client gems operate in parallel without concern about conflicting monkey-patches.
|
|
17
16
|
|
|
@@ -30,6 +29,14 @@ gem "schema_monkey", "~> <MAJOR>.<MINOR>", ">= <MAJOR>.<MINOR>.<PATCH>"
|
|
|
30
29
|
|
|
31
30
|
SchemaMonkey follows semantic versioning; it's a good idea to explicitly use the `~>` and `>=` dependencies to make sure your gem's clients don't accidentally pull in a version of SchemaMonkey that your gem isn't compatible with.
|
|
32
31
|
|
|
32
|
+
To use with a rails app, also include
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
gem "schema_monkey_rails"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
which creates a Railtie to insert SchemaMonkey appropriately into the rails stack.
|
|
39
|
+
|
|
33
40
|
## Compatibility
|
|
34
41
|
|
|
35
42
|
SchemaMonkey is tested on:
|
|
@@ -44,7 +51,7 @@ SchemaMonkey is tested on:
|
|
|
44
51
|
## Usage
|
|
45
52
|
|
|
46
53
|
|
|
47
|
-
**Sorry -- no real documentation yet.
|
|
54
|
+
**Sorry -- no real documentation yet. See examples in [schema_plus_indexes](https://github/SchemaPlus/schema_plus_indexes) and [schema_plus_pg_indexes](https://github/SchemaPlus/schema_plus_pg_indexes)**
|
|
48
55
|
|
|
49
56
|
|
|
50
57
|
|
|
@@ -55,7 +62,13 @@ the standard protocol: fork, feature branch, develop, push, and issue pull reque
|
|
|
55
62
|
|
|
56
63
|
Some things to know about to help you develop and test:
|
|
57
64
|
|
|
58
|
-
*
|
|
65
|
+
* SchemaMonkey is a wrapper around two subparts:
|
|
66
|
+
|
|
67
|
+
* `SchemaMonkey::Tool` provides the convention-based mechanism for registering clients that extend ActiveRecord using `include`'s and middleware.
|
|
68
|
+
|
|
69
|
+
* `SchemaMonkey::CoreExtensions` defines the ActiveRecord extension API. It is itself just the first client registered with `SchemaMonkey::Tool`. **Ugh. Currently no specs for `SchemaMonkey::CoreExtensions`; testing indirectly by testing the client gems that use it. Working on it...**
|
|
70
|
+
|
|
71
|
+
One day might actually split these into separate gems to decouple their development and testing. And actually the middleware mechanism of `SchemaMonkey::Tool` could be a split out separate gem.
|
|
59
72
|
|
|
60
73
|
* **schema_dev**: SchemaMonkey uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
|
|
61
74
|
facilitate running rspec tests on the matrix of ruby, rails, and database
|
data/lib/schema_monkey.rb
CHANGED
|
@@ -1,45 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require 'key_struct'
|
|
4
|
-
require 'middleware'
|
|
5
|
-
require 'active_record'
|
|
6
|
-
require 'active_support/core_ext/string'
|
|
7
|
-
|
|
8
|
-
require_relative "schema_monkey/client"
|
|
9
|
-
require_relative "schema_monkey/middleware"
|
|
10
|
-
require_relative "schema_monkey/module"
|
|
11
|
-
require_relative "schema_monkey/active_record/base"
|
|
12
|
-
require_relative "schema_monkey/active_record/connection_adapters/abstract_adapter"
|
|
13
|
-
require_relative "schema_monkey/active_record/connection_adapters/table_definition"
|
|
14
|
-
require_relative 'schema_monkey/active_record/connection_adapters/schema_statements'
|
|
15
|
-
require_relative 'schema_monkey/active_record/migration/command_recorder'
|
|
16
|
-
require_relative 'schema_monkey/active_record/schema_dumper'
|
|
17
|
-
require_relative 'schema_monkey/rake'
|
|
1
|
+
require_relative "schema_monkey/core_extensions"
|
|
2
|
+
require_relative "schema_monkey/tool"
|
|
18
3
|
|
|
4
|
+
#
|
|
5
|
+
# Middleware contents will be created dynamically
|
|
6
|
+
#
|
|
19
7
|
module SchemaMonkey
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
DBMS = [:PostgreSQL, :Mysql, :SQLite3]
|
|
23
|
-
|
|
24
|
-
module ActiveRecord
|
|
25
|
-
module ConnectionAdapters
|
|
26
|
-
autoload :PostgresqlAdapter, 'schema_monkey/active_record/connection_adapters/postgresql_adapter'
|
|
27
|
-
autoload :Mysql2Adapter, 'schema_monkey/active_record/connection_adapters/mysql2_adapter'
|
|
28
|
-
autoload :Sqlite3Adapter, 'schema_monkey/active_record/connection_adapters/sqlite3_adapter'
|
|
29
|
-
end
|
|
8
|
+
module Middleware
|
|
30
9
|
end
|
|
10
|
+
end
|
|
31
11
|
|
|
12
|
+
#
|
|
13
|
+
# Wrap public API of SchemaMonkey::Tool
|
|
14
|
+
#
|
|
15
|
+
module SchemaMonkey
|
|
32
16
|
def self.register(mod)
|
|
33
|
-
|
|
17
|
+
Tool::register(mod)
|
|
34
18
|
end
|
|
35
19
|
|
|
36
|
-
def self.
|
|
37
|
-
|
|
20
|
+
def self.insert(opts={})
|
|
21
|
+
Tool::insert(opts)
|
|
38
22
|
end
|
|
39
23
|
|
|
40
|
-
def self.
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
def self.include_once(*args)
|
|
25
|
+
Tool::Module.include_once(*args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module Rake
|
|
29
|
+
def self.insert(*args)
|
|
30
|
+
Tool::Rake::insert(*args)
|
|
31
|
+
end
|
|
43
32
|
end
|
|
44
33
|
|
|
34
|
+
MiddlewareError = Tool::MiddlewareError
|
|
45
35
|
end
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# Register CoreExtensions
|
|
39
|
+
#
|
|
40
|
+
SchemaMonkey::Tool.register(SchemaMonkey::CoreExtensions)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
require 'key_struct'
|
|
3
|
+
|
|
4
|
+
module SchemaMonkey
|
|
5
|
+
module CoreExtensions
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module ConnectionAdapters
|
|
8
|
+
DIR = Pathname.new(__FILE__).dirname + 'core_extensions/active_record/connection_adapters'
|
|
9
|
+
autoload :PostgresqlAdapter, DIR + 'postgresql_adapter'
|
|
10
|
+
autoload :Mysql2Adapter, DIR + 'mysql2_adapter'
|
|
11
|
+
autoload :Sqlite3Adapter, DIR + 'sqlite3_adapter'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require_relative "core_extensions/active_record/base"
|
|
18
|
+
require_relative "core_extensions/active_record/connection_adapters/abstract_adapter"
|
|
19
|
+
require_relative "core_extensions/active_record/connection_adapters/table_definition"
|
|
20
|
+
require_relative 'core_extensions/active_record/connection_adapters/schema_statements'
|
|
21
|
+
require_relative 'core_extensions/active_record/migration/command_recorder'
|
|
22
|
+
require_relative 'core_extensions/active_record/schema_dumper'
|
|
23
|
+
require_relative "core_extensions/middleware"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
|
|
4
4
|
module Base
|
|
@@ -15,13 +15,13 @@ module SchemaMonkey
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def columns_with_schema_monkey
|
|
18
|
-
Middleware::Model::Columns.start
|
|
18
|
+
SchemaMonkey::Middleware::Model::Columns.start(model: self, columns: []) { |env|
|
|
19
19
|
env.columns += columns_without_schema_monkey
|
|
20
|
-
|
|
20
|
+
}.columns
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def reset_column_information_with_schema_monkey
|
|
24
|
-
Middleware::Model::ResetColumnInformation.start
|
|
24
|
+
SchemaMonkey::Middleware::Model::ResetColumnInformation.start(model: self) do |env|
|
|
25
25
|
reset_column_information_without_schema_monkey
|
|
26
26
|
end
|
|
27
27
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module ConnectionAdapters
|
|
4
4
|
module AbstractAdapter
|
|
@@ -27,9 +27,9 @@ module SchemaMonkey
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def add_column_options_with_schema_monkey!(sql, options)
|
|
30
|
-
Middleware::Migration::ColumnOptionsSql.start
|
|
30
|
+
SchemaMonkey::Middleware::Migration::ColumnOptionsSql.start(caller: self, connection: self.instance_variable_get('@conn'), sql: sql, options: options) { |env|
|
|
31
31
|
add_column_options_without_schema_monkey! env.sql, env.options
|
|
32
|
-
|
|
32
|
+
}.sql
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module ConnectionAdapters
|
|
4
4
|
module Mysql2Adapter
|
|
@@ -8,21 +8,21 @@ module SchemaMonkey
|
|
|
8
8
|
alias_method_chain :indexes, :schema_monkey
|
|
9
9
|
alias_method_chain :tables, :schema_monkey
|
|
10
10
|
end
|
|
11
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Column
|
|
12
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Reference
|
|
13
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Index
|
|
11
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Column
|
|
12
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Reference
|
|
13
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Index
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def indexes_with_schema_monkey(table_name, query_name=nil)
|
|
17
|
-
Middleware::Query::Indexes.start
|
|
17
|
+
SchemaMonkey::Middleware::Query::Indexes.start(connection: self, table_name: table_name, query_name: query_name, index_definitions: []) { |env|
|
|
18
18
|
env.index_definitions += indexes_without_schema_monkey env.table_name, env.query_name
|
|
19
|
-
|
|
19
|
+
}.index_definitions
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def tables_with_schema_monkey(query_name=nil, database=nil, like=nil)
|
|
23
|
-
Middleware::Query::Tables.start
|
|
23
|
+
SchemaMonkey::Middleware::Query::Tables.start(connection: self, query_name: query_name, database: database, like: like, tables: []) { |env|
|
|
24
24
|
env.tables += tables_without_schema_monkey env.query_name, env.database, env.like
|
|
25
|
-
|
|
25
|
+
}.tables
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
data/lib/schema_monkey/core_extensions/active_record/connection_adapters/postgresql_adapter.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
|
+
module ActiveRecord
|
|
3
|
+
module ConnectionAdapters
|
|
4
|
+
module PostgresqlAdapter
|
|
5
|
+
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.class_eval do
|
|
8
|
+
alias_method_chain :exec_cache, :schema_monkey
|
|
9
|
+
alias_method_chain :indexes, :schema_monkey
|
|
10
|
+
end
|
|
11
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Reference
|
|
12
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Column
|
|
13
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Index
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def exec_cache_with_schema_monkey(sql, name, binds)
|
|
17
|
+
SchemaMonkey::Middleware::Query::ExecCache.start(connection: self, sql: sql, name: name, binds: binds) { |env|
|
|
18
|
+
env.result = exec_cache_without_schema_monkey(env.sql, env.name, env.binds)
|
|
19
|
+
}.result
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def indexes_with_schema_monkey(table_name, query_name=nil)
|
|
23
|
+
SchemaMonkey::Middleware::Query::Indexes.start(connection: self, table_name: table_name, query_name: query_name, index_definitions: []) { |env|
|
|
24
|
+
env.index_definitions += indexes_without_schema_monkey env.table_name, env.query_name
|
|
25
|
+
}.index_definitions
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module ConnectionAdapters
|
|
4
4
|
module SchemaStatements
|
|
@@ -13,13 +13,12 @@ module SchemaMonkey
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
IndexComponentsSql = KeyStruct[:name, :type, :columns, :options, :algorithm, :using]
|
|
17
|
+
|
|
16
18
|
def add_index_options_with_schema_monkey(table_name, column_names, options={})
|
|
17
|
-
|
|
18
|
-
Middleware::Migration::IndexComponentsSql.start connection: self, table_name: table_name, column_names: Array.wrap(column_names), options: options.deep_dup do |env|
|
|
19
|
-
cache << env
|
|
19
|
+
env = SchemaMonkey::Middleware::Migration::IndexComponentsSql.start(connection: self, table_name: table_name, column_names: Array.wrap(column_names), options: options.deep_dup, sql: IndexComponentsSql.new) { |env|
|
|
20
20
|
env.sql.name, env.sql.type, env.sql.columns, env.sql.options, env.sql.algorithm, env.sql.using = add_index_options_without_schema_monkey(env.table_name, env.column_names, env.options)
|
|
21
|
-
|
|
22
|
-
env = cache[0]
|
|
21
|
+
}
|
|
23
22
|
[env.sql.name, env.sql.type, env.sql.columns, env.sql.options, env.sql.algorithm, env.sql.using]
|
|
24
23
|
end
|
|
25
24
|
|
|
@@ -38,13 +37,13 @@ module SchemaMonkey
|
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
def add_column_with_schema_monkey(table_name, name, type, options = {})
|
|
41
|
-
Middleware::Migration::Column.start
|
|
40
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :add, table_name: table_name, column_name: name, type: type, options: options.deep_dup) do |env|
|
|
42
41
|
add_column_without_schema_monkey env.table_name, env.column_name, env.type, env.options
|
|
43
42
|
end
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
def change_column_with_schema_monkey(table_name, name, type, options = {})
|
|
47
|
-
Middleware::Migration::Column.start
|
|
46
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :change, table_name: table_name, column_name: name, type: type, options: options.deep_dup) do |env|
|
|
48
47
|
change_column_without_schema_monkey env.table_name, env.column_name, env.type, env.options
|
|
49
48
|
end
|
|
50
49
|
end
|
|
@@ -57,7 +56,7 @@ module SchemaMonkey
|
|
|
57
56
|
end
|
|
58
57
|
end
|
|
59
58
|
def add_reference_with_schema_monkey(table_name, name, options = {})
|
|
60
|
-
Middleware::Migration::Column.start
|
|
59
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :add, table_name: table_name, column_name: "#{name}_id", type: :reference, options: options.deep_dup) do |env|
|
|
61
60
|
add_reference_without_schema_monkey env.table_name, env.column_name.sub(/_id$/, ''), env.options
|
|
62
61
|
end
|
|
63
62
|
end
|
|
@@ -72,7 +71,7 @@ module SchemaMonkey
|
|
|
72
71
|
def add_index_with_schema_monkey(*args)
|
|
73
72
|
options = args.extract_options!
|
|
74
73
|
table_name, column_names = args
|
|
75
|
-
Middleware::Migration::Index.start
|
|
74
|
+
SchemaMonkey::Middleware::Migration::Index.start(caller: self, operation: :add, table_name: table_name, column_names: column_names, options: options.deep_dup) do |env|
|
|
76
75
|
add_index_without_schema_monkey env.table_name, env.column_names, env.options
|
|
77
76
|
end
|
|
78
77
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module ConnectionAdapters
|
|
4
4
|
module Sqlite3Adapter
|
|
@@ -8,21 +8,21 @@ module SchemaMonkey
|
|
|
8
8
|
alias_method_chain :indexes, :schema_monkey
|
|
9
9
|
alias_method_chain :tables, :schema_monkey
|
|
10
10
|
end
|
|
11
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Column
|
|
12
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Reference
|
|
13
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Index
|
|
11
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Column
|
|
12
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Reference
|
|
13
|
+
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::CoreExtensions::ActiveRecord::ConnectionAdapters::SchemaStatements::Index
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def indexes_with_schema_monkey(table_name, query_name=nil)
|
|
17
|
-
Middleware::Query::Indexes.start
|
|
17
|
+
SchemaMonkey::Middleware::Query::Indexes.start(connection: self, table_name: table_name, query_name: query_name, index_definitions: []) { |env|
|
|
18
18
|
env.index_definitions += indexes_without_schema_monkey env.table_name, env.query_name
|
|
19
|
-
|
|
19
|
+
}.index_definitions
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def tables_with_schema_monkey(query_name=nil, table_name=nil)
|
|
23
|
-
Middleware::Query::Tables.start
|
|
23
|
+
SchemaMonkey::Middleware::Query::Tables.start(connection: self, query_name: query_name, table_name: table_name, tables: []) { |env|
|
|
24
24
|
env.tables += tables_without_schema_monkey env.query_name, env.table_name
|
|
25
|
-
|
|
25
|
+
}.tables
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module ConnectionAdapters
|
|
4
4
|
module TableDefinition
|
|
@@ -12,19 +12,19 @@ module SchemaMonkey
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def column_with_schema_monkey(name, type, options = {})
|
|
15
|
-
Middleware::Migration::Column.start
|
|
15
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :define, table_name: self.name, column_name: name, type: type, options: options.deep_dup) do |env|
|
|
16
16
|
column_without_schema_monkey env.column_name, env.type, env.options
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def references_with_schema_monkey(name, options = {})
|
|
21
|
-
Middleware::Migration::Column.start
|
|
21
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :define, table_name: self.name, column_name: "#{name}_id", type: :reference, options: options.deep_dup) do |env|
|
|
22
22
|
references_without_schema_monkey env.column_name.sub(/_id$/, ''), env.options
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def belongs_to_with_schema_monkey(name, options = {})
|
|
27
|
-
Middleware::Migration::Column.start
|
|
27
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :define, table_name: self.name, column_name: "#{name}_id", type: :reference, options: options.deep_dup) do |env|
|
|
28
28
|
belongs_to_without_schema_monkey env.column_name.sub(/_id$/, ''), env.options
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -32,7 +32,7 @@ module SchemaMonkey
|
|
|
32
32
|
def index_with_schema_monkey(*args)
|
|
33
33
|
options = args.extract_options!
|
|
34
34
|
column_name = args.first
|
|
35
|
-
Middleware::Migration::Index.start
|
|
35
|
+
SchemaMonkey::Middleware::Migration::Index.start(caller: self, operation: :define, table_name: self.name, column_names: column_name, options: options.deep_dup) do |env|
|
|
36
36
|
index_without_schema_monkey env.column_names, env.options
|
|
37
37
|
end
|
|
38
38
|
end
|
data/lib/schema_monkey/{active_record → core_extensions/active_record}/migration/command_recorder.rb
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module Migration
|
|
4
4
|
module CommandRecorder
|
|
@@ -9,7 +9,7 @@ module SchemaMonkey
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def add_column_with_schema_monkey(table_name, column_name, type, options = {})
|
|
12
|
-
Middleware::Migration::Column.start
|
|
12
|
+
SchemaMonkey::Middleware::Migration::Column.start(caller: self, operation: :record, table_name: table_name, column_name: column_name, type: type, options: options.deep_dup) do |env|
|
|
13
13
|
add_column_without_schema_monkey env.table_name, env.column_name, env.type, env.options
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'ostruct'
|
|
2
2
|
require 'tsort'
|
|
3
3
|
|
|
4
|
-
module SchemaMonkey
|
|
4
|
+
module SchemaMonkey::CoreExtensions
|
|
5
5
|
module ActiveRecord
|
|
6
6
|
module SchemaDumper
|
|
7
7
|
|
|
@@ -157,7 +157,7 @@ module SchemaMonkey
|
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
def extensions_with_schema_monkey(_)
|
|
160
|
-
Middleware::Dumper::Extensions.start
|
|
160
|
+
SchemaMonkey::Middleware::Dumper::Extensions.start(dumper: self, connection: @connection, dump: @dump, extensions: @dump.extensions) do |env|
|
|
161
161
|
stream = StringIO.new
|
|
162
162
|
extensions_without_schema_monkey(stream)
|
|
163
163
|
env.dump.extensions << stream.string unless stream.string.blank?
|
|
@@ -165,13 +165,13 @@ module SchemaMonkey
|
|
|
165
165
|
end
|
|
166
166
|
|
|
167
167
|
def tables_with_schema_monkey(_)
|
|
168
|
-
Middleware::Dumper::Tables.start
|
|
168
|
+
SchemaMonkey::Middleware::Dumper::Tables.start(dumper: self, connection: @connection, dump: @dump) do |env|
|
|
169
169
|
tables_without_schema_monkey(nil)
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
def table_with_schema_monkey(table, _)
|
|
174
|
-
Middleware::Dumper::Table.start
|
|
174
|
+
SchemaMonkey::Middleware::Dumper::Table.start(dumper: self, connection: @connection, dump: @dump, table: @dump.tables[table] = Dump::Table.new(name: table)) do |env|
|
|
175
175
|
stream = StringIO.new
|
|
176
176
|
table_without_schema_monkey(env.table.name, stream)
|
|
177
177
|
m = stream.string.match %r{
|
|
@@ -204,7 +204,7 @@ module SchemaMonkey
|
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
def indexes_with_schema_monkey(table, _)
|
|
207
|
-
Middleware::Dumper::Indexes.start
|
|
207
|
+
SchemaMonkey::Middleware::Dumper::Indexes.start(dumper: self, connection: @connection, dump: @dump, table: @dump.tables[table]) do |env|
|
|
208
208
|
stream = StringIO.new
|
|
209
209
|
indexes_without_schema_monkey(env.table.name, stream)
|
|
210
210
|
env.table.indexes += stream.string.split("\n").map { |string|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module SchemaMonkey::CoreExtensions
|
|
2
|
+
module Middleware
|
|
3
|
+
module Query
|
|
4
|
+
module ExecCache
|
|
5
|
+
ENV = [:connection, :sql, :name, :binds, :result]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Tables
|
|
9
|
+
# :database and :like are only for mysql
|
|
10
|
+
# :table_name is only for sqlite3
|
|
11
|
+
ENV = [:connection, :query_name, :table_name, :database, :like, :tables]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Indexes
|
|
15
|
+
ENV = [:connection, :table_name, :query_name, :index_definitions]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module Migration
|
|
20
|
+
module Column
|
|
21
|
+
ENV = [:caller, :operation, :table_name, :column_name, :type, :options]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module ColumnOptionsSql
|
|
25
|
+
ENV = [:caller, :connection, :sql, :options]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module Index
|
|
29
|
+
ENV = [:caller, :operation, :table_name, :column_names, :options]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module IndexComponentsSql
|
|
33
|
+
ENV = [:connection, :table_name, :column_names, :options, :sql]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
module Dumper
|
|
38
|
+
module Extensions
|
|
39
|
+
ENV = [:dumper, :connection, :dump, :extensions]
|
|
40
|
+
end
|
|
41
|
+
module Tables
|
|
42
|
+
ENV = [:dumper, :connection, :dump]
|
|
43
|
+
end
|
|
44
|
+
module Table
|
|
45
|
+
ENV = [:dumper, :connection, :dump, :table]
|
|
46
|
+
end
|
|
47
|
+
module Indexes
|
|
48
|
+
ENV = [:dumper, :connection, :dump, :table]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module Model
|
|
53
|
+
module Columns
|
|
54
|
+
ENV = [:model, :columns]
|
|
55
|
+
end
|
|
56
|
+
module ResetColumnInformation
|
|
57
|
+
ENV = [:model]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'hash_keyword_args'
|
|
2
|
+
require 'its-it'
|
|
3
|
+
require 'key_struct'
|
|
4
|
+
require 'active_support/core_ext/string'
|
|
5
|
+
|
|
6
|
+
require_relative "tool/client"
|
|
7
|
+
require_relative "tool/errors"
|
|
8
|
+
require_relative "tool/module"
|
|
9
|
+
require_relative "tool/monkey"
|
|
10
|
+
require_relative "tool/stack"
|
|
11
|
+
require_relative 'tool/rake'
|
|
12
|
+
|
|
13
|
+
module SchemaMonkey
|
|
14
|
+
module Tool
|
|
15
|
+
|
|
16
|
+
DBMS = [:PostgreSQL, :Mysql, :SQLite3]
|
|
17
|
+
|
|
18
|
+
def self.register(mod)
|
|
19
|
+
monkey.register(mod)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.insert(opts={})
|
|
23
|
+
monkey.insert(opts)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def self.monkey
|
|
29
|
+
@monkey ||= Monkey.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.reset_for_rspec
|
|
33
|
+
@monkey = nil
|
|
34
|
+
self.reset_middleware
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.reset_middleware
|
|
38
|
+
SchemaMonkey.send :remove_const, :Middleware
|
|
39
|
+
SchemaMonkey.send :const_set, :Middleware, ::Module.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::Tool
|
|
2
2
|
class Client
|
|
3
|
-
|
|
3
|
+
attr_reader :monkey
|
|
4
|
+
|
|
5
|
+
def initialize(monkey, mod)
|
|
6
|
+
@monkey = monkey
|
|
4
7
|
@root = mod
|
|
5
8
|
@inserted = {}
|
|
6
9
|
end
|
|
@@ -14,23 +17,27 @@ module SchemaMonkey
|
|
|
14
17
|
|
|
15
18
|
def include_modules(opts={})
|
|
16
19
|
opts = opts.keyword_args(:dbm)
|
|
20
|
+
# Kernel.warn "--- include modules for #{@root}, dbm=#{opts.dbm.inspect}"
|
|
17
21
|
find_modules(:ActiveRecord, dbm: opts.dbm).each do |mod|
|
|
18
22
|
next if mod.is_a? Class
|
|
19
23
|
component = mod.to_s.sub(/^#{@root}::ActiveRecord::/, '')
|
|
20
24
|
component = component.gsub(/#{opts.dbm}/i, opts.dbm.to_s) if opts.dbm # canonicalize case
|
|
21
|
-
next unless base = Module.
|
|
22
|
-
# Kernel.warn "including #{mod}"
|
|
25
|
+
next unless base = Module.const_lookup(::ActiveRecord, component)
|
|
26
|
+
# Kernel.warn "including #{mod} (dbm=#{opts.dbm})"
|
|
23
27
|
Module.include_once base, mod
|
|
24
28
|
end
|
|
25
29
|
end
|
|
26
30
|
|
|
27
31
|
def insert_middleware(opts={})
|
|
28
32
|
opts = opts.keyword_args(:dbm)
|
|
29
|
-
find_modules(:Middleware, dbm: opts.dbm
|
|
33
|
+
find_modules(:Middleware, dbm: opts.dbm).each do |mod|
|
|
30
34
|
next if @inserted[mod]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
|
|
36
|
+
stack_path = mod.to_s.sub(/^#{@root}::Middleware::/, '')
|
|
37
|
+
stack_path = stack_path.split('::').reject(&it =~/\b#{opts.dbm}\b/i).join('::') if opts.dbm
|
|
38
|
+
|
|
39
|
+
monkey.insert_middleware_hook(mod, stack_path: stack_path) unless stack_path.empty?
|
|
40
|
+
|
|
34
41
|
@inserted[mod] = true
|
|
35
42
|
end
|
|
36
43
|
end
|
|
@@ -38,19 +45,18 @@ module SchemaMonkey
|
|
|
38
45
|
private
|
|
39
46
|
|
|
40
47
|
def find_modules(container, opts={})
|
|
41
|
-
opts = opts.keyword_args(dbm: nil
|
|
42
|
-
return [] unless (container = Module.
|
|
48
|
+
opts = opts.keyword_args(dbm: nil)
|
|
49
|
+
return [] unless (container = Module.const_lookup @root, container)
|
|
43
50
|
|
|
44
51
|
if opts.dbm
|
|
45
52
|
accept = /\b#{opts.dbm}/i
|
|
46
53
|
reject = nil
|
|
47
54
|
else
|
|
48
55
|
accept = nil
|
|
49
|
-
reject = /\b#{
|
|
56
|
+
reject = /\b(#{DBMS.join('|')})/i
|
|
50
57
|
end
|
|
51
58
|
|
|
52
59
|
modules = []
|
|
53
|
-
modules << container if opts.and_self
|
|
54
60
|
modules += Module.descendants(container, can_load: accept)
|
|
55
61
|
modules.select!(&it.to_s =~ accept) if accept
|
|
56
62
|
modules.reject!(&it.to_s =~ reject) if reject
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
1
|
+
module SchemaMonkey::Tool
|
|
2
2
|
module Module
|
|
3
3
|
extend self
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ module SchemaMonkey
|
|
|
9
9
|
# ruby 2.* supports mod.const_get("Component::Path") but ruby 1.9.3
|
|
10
10
|
# doesn't. And neither has an option to return nil rather than raising
|
|
11
11
|
# a NameError
|
|
12
|
-
def
|
|
12
|
+
def const_lookup(mod, name)
|
|
13
13
|
name.to_s.split('::').map(&:to_sym).each do |component|
|
|
14
14
|
begin
|
|
15
15
|
mod = mod.const_get(component, false)
|
|
@@ -29,5 +29,12 @@ module SchemaMonkey
|
|
|
29
29
|
children + children.flat_map {|c| descendants(c, can_load: opts.can_load) }
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def mkpath(mod, path)
|
|
33
|
+
path.split('::').each do |component|
|
|
34
|
+
mod = const_lookup(mod, component) || mod.const_set(component, ::Module.new)
|
|
35
|
+
end
|
|
36
|
+
mod
|
|
37
|
+
end
|
|
38
|
+
|
|
32
39
|
end
|
|
33
40
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module SchemaMonkey::Tool
|
|
2
|
+
|
|
3
|
+
# The main manager for the monkey patches. Singleton instance
|
|
4
|
+
# created by SchemaMonkey.monkey
|
|
5
|
+
|
|
6
|
+
class Monkey
|
|
7
|
+
|
|
8
|
+
attr_reader :clients, :stacks
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@clients = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def register(mod)
|
|
15
|
+
clients << Client.new(self, mod)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def insert(opts={})
|
|
19
|
+
opts = opts.keyword_args(:dbm)
|
|
20
|
+
clients.each &it.insert(dbm: opts.dbm)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def insert_middleware_hook(mod, opts={})
|
|
24
|
+
opts = opts.keyword_args(stack_path: :required)
|
|
25
|
+
|
|
26
|
+
return unless Stack.is_hook?(mod)
|
|
27
|
+
|
|
28
|
+
stack = Module.const_lookup SchemaMonkey::Middleware, opts.stack_path
|
|
29
|
+
env = Module.const_lookup mod, "ENV"
|
|
30
|
+
|
|
31
|
+
case
|
|
32
|
+
when stack && env
|
|
33
|
+
raise MiddlewareError, "#{mod}::ENV: stack #{stack} is already defined"
|
|
34
|
+
when !stack && !env
|
|
35
|
+
raise MiddlewareError, "#{mod}: No stack #{SchemaMonkey::Middleware}::#{opts.stack_path}"
|
|
36
|
+
when !stack && env
|
|
37
|
+
stack = Module.mkpath SchemaMonkey::Middleware, opts.stack_path
|
|
38
|
+
stack.send :extend, Stack::StartMethod
|
|
39
|
+
stack.send :stack=, Stack.new(module: stack, env: env)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
stack.stack.append(mod)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module SchemaMonkey::Tool
|
|
2
|
+
class Stack
|
|
3
|
+
def initialize(opts={})
|
|
4
|
+
opts = opts.keyword_args(module: :required, env: :required)
|
|
5
|
+
@module = opts.module
|
|
6
|
+
@env_class = @module.const_set "Env", KeyStruct[*opts.env]
|
|
7
|
+
@hooks = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.is_hook?(mod)
|
|
11
|
+
return true if (mod.instance_methods & [:before, :around, :after, :implementation]).any?
|
|
12
|
+
return true if Module.const_lookup mod, "ENV"
|
|
13
|
+
false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def append(mod)
|
|
17
|
+
hook = Hook.new(self, mod)
|
|
18
|
+
@hooks.last._next = hook if @hooks.any?
|
|
19
|
+
@hooks << hook
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def start(env_opts, &implementation)
|
|
23
|
+
env = @env_class.new(env_opts)
|
|
24
|
+
@implementation = implementation
|
|
25
|
+
|
|
26
|
+
@hooks.each do |hook|
|
|
27
|
+
hook.before env if hook.respond_to? :before
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@hooks.first._call(env)
|
|
31
|
+
|
|
32
|
+
@hooks.each do |hook|
|
|
33
|
+
hook.after env if hook.respond_to? :after
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
env
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def call_implementation(env)
|
|
40
|
+
if hook = @hooks.select(&it.respond_to?(:implementation)).last
|
|
41
|
+
hook.implementation(env)
|
|
42
|
+
elsif @implementation
|
|
43
|
+
@implementation.call env
|
|
44
|
+
else
|
|
45
|
+
raise MiddlewareError, "No implementation for middleware stack #{@module}"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Hook
|
|
50
|
+
attr_accessor :_next
|
|
51
|
+
|
|
52
|
+
def initialize(stack, mod)
|
|
53
|
+
@stack = stack
|
|
54
|
+
singleton_class.send :include, mod
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def _call(env)
|
|
58
|
+
if respond_to? :around
|
|
59
|
+
around(env) { |env|
|
|
60
|
+
_continue env
|
|
61
|
+
}
|
|
62
|
+
else
|
|
63
|
+
_continue env
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def _continue(env)
|
|
68
|
+
if self._next
|
|
69
|
+
self._next._call(env)
|
|
70
|
+
else
|
|
71
|
+
@stack.call_implementation(env)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
module StartMethod
|
|
77
|
+
attr_reader :stack
|
|
78
|
+
|
|
79
|
+
def start(env, &block)
|
|
80
|
+
stack.start(env, &block)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def stack=(stack)
|
|
86
|
+
@stack = stack
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
File without changes
|
data/schema_monkey.gemspec
CHANGED
|
@@ -22,7 +22,6 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.add_dependency "hash_keyword_args"
|
|
23
23
|
spec.add_dependency "its-it"
|
|
24
24
|
spec.add_dependency "key_struct"
|
|
25
|
-
spec.add_dependency "middleware", "~> 0.1"
|
|
26
25
|
|
|
27
26
|
spec.add_development_dependency "bundler", "~> 1.7"
|
|
28
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe SchemaMonkey::Middleware do
|
|
4
|
+
|
|
5
|
+
When(:insertion) { SchemaMonkey.insert }
|
|
6
|
+
|
|
7
|
+
context "with stack registered" do
|
|
8
|
+
|
|
9
|
+
Given { SchemaMonkey.register make_definition }
|
|
10
|
+
|
|
11
|
+
Then { expect(defined?(SchemaMonkey::Middleware::Group::Stack)).to be_truthy }
|
|
12
|
+
|
|
13
|
+
context "when start with no implementation" do
|
|
14
|
+
|
|
15
|
+
When(:env) { SchemaMonkey::Middleware::Group::Stack.start result: [] }
|
|
16
|
+
|
|
17
|
+
Then { expect(env).to have_failed(SchemaMonkey::MiddlewareError, /implementation/) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when start with inline implementation" do
|
|
21
|
+
|
|
22
|
+
When(:env) { SchemaMonkey::Middleware::Group::Stack.start result: [] { |env| env.result << :inline } }
|
|
23
|
+
|
|
24
|
+
Then { expect(env.result).to eq [:inline] }
|
|
25
|
+
|
|
26
|
+
context "if register client1" do
|
|
27
|
+
|
|
28
|
+
Given { SchemaMonkey.register make_client(1) }
|
|
29
|
+
|
|
30
|
+
Then { expect(env.result).to eq [:before1, :around_pre1, :implementation1, :around_post1, :after1 ] }
|
|
31
|
+
|
|
32
|
+
context "if register client2" do
|
|
33
|
+
|
|
34
|
+
Given { SchemaMonkey.register make_client(2) }
|
|
35
|
+
|
|
36
|
+
Then { expect(env.result).to eq [:before1, :before2, :around_pre1, :around_pre2, :implementation2, :around_post2, :around_post1, :after1, :after2 ] }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "if register again" do
|
|
42
|
+
Given { SchemaMonkey.register make_definition }
|
|
43
|
+
Then { expect(insertion).to have_failed(SchemaMonkey::MiddlewareError, /already defined/i) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "without stack registered" do
|
|
48
|
+
context "if register client1" do
|
|
49
|
+
Given { SchemaMonkey.register make_client(1) }
|
|
50
|
+
|
|
51
|
+
Then { expect(insertion).to have_failed(SchemaMonkey::MiddlewareError, /no stack/i) }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def make_definition
|
|
57
|
+
Module.new.tap(&it.module_eval(<<-END))
|
|
58
|
+
module Middleware
|
|
59
|
+
module Group
|
|
60
|
+
module Stack
|
|
61
|
+
ENV = [:result]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
END
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def make_client(n)
|
|
69
|
+
Module.new.tap(&it.module_eval(<<-END))
|
|
70
|
+
module Middleware
|
|
71
|
+
module Group
|
|
72
|
+
module Stack
|
|
73
|
+
def before(env)
|
|
74
|
+
env.result << :"before#{n}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def after(env)
|
|
78
|
+
env.result << :"after#{n}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def around(env)
|
|
82
|
+
env.result << :"around_pre#{n}"
|
|
83
|
+
yield env
|
|
84
|
+
env.result << :"around_post#{n}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def implementation(env)
|
|
88
|
+
env.result << :"implementation#{n}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
END
|
|
94
|
+
end
|
|
95
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
require 'simplecov'
|
|
2
2
|
require 'simplecov-gem-profile'
|
|
3
|
-
SimpleCov.start "gem"
|
|
3
|
+
SimpleCov.start "gem" do
|
|
4
|
+
add_filter "/tasks/"
|
|
5
|
+
end
|
|
4
6
|
|
|
5
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
6
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
@@ -17,6 +19,9 @@ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
|
|
|
17
19
|
|
|
18
20
|
RSpec.configure do |config|
|
|
19
21
|
config.warnings = true
|
|
22
|
+
config.after(:each) do
|
|
23
|
+
SchemaMonkey::Tool.reset_for_rspec
|
|
24
|
+
end
|
|
20
25
|
end
|
|
21
26
|
|
|
22
27
|
SimpleCov.command_name "[ruby #{RUBY_VERSION} - ActiveRecord #{::ActiveRecord::VERSION::STRING} - #{ActiveRecord::Base.connection.adapter_name}]"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schema_monkey
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ronen barzel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-02-
|
|
11
|
+
date: 2015-02-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -66,20 +66,6 @@ dependencies:
|
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: middleware
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0.1'
|
|
76
|
-
type: :runtime
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0.1'
|
|
83
69
|
- !ruby/object:Gem::Dependency
|
|
84
70
|
name: bundler
|
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -198,24 +184,30 @@ files:
|
|
|
198
184
|
- gemfiles/activerecord-4.2/Gemfile.postgresql
|
|
199
185
|
- gemfiles/activerecord-4.2/Gemfile.sqlite3
|
|
200
186
|
- lib/schema_monkey.rb
|
|
201
|
-
- lib/schema_monkey/
|
|
202
|
-
- lib/schema_monkey/active_record/
|
|
203
|
-
- lib/schema_monkey/active_record/connection_adapters/
|
|
204
|
-
- lib/schema_monkey/active_record/connection_adapters/
|
|
205
|
-
- lib/schema_monkey/active_record/connection_adapters/
|
|
206
|
-
- lib/schema_monkey/active_record/connection_adapters/
|
|
207
|
-
- lib/schema_monkey/active_record/connection_adapters/
|
|
208
|
-
- lib/schema_monkey/active_record/
|
|
209
|
-
- lib/schema_monkey/active_record/
|
|
210
|
-
- lib/schema_monkey/
|
|
211
|
-
- lib/schema_monkey/middleware.rb
|
|
212
|
-
- lib/schema_monkey/
|
|
213
|
-
- lib/schema_monkey/
|
|
214
|
-
- lib/schema_monkey/
|
|
187
|
+
- lib/schema_monkey/core_extensions.rb
|
|
188
|
+
- lib/schema_monkey/core_extensions/active_record/base.rb
|
|
189
|
+
- lib/schema_monkey/core_extensions/active_record/connection_adapters/abstract_adapter.rb
|
|
190
|
+
- lib/schema_monkey/core_extensions/active_record/connection_adapters/mysql2_adapter.rb
|
|
191
|
+
- lib/schema_monkey/core_extensions/active_record/connection_adapters/postgresql_adapter.rb
|
|
192
|
+
- lib/schema_monkey/core_extensions/active_record/connection_adapters/schema_statements.rb
|
|
193
|
+
- lib/schema_monkey/core_extensions/active_record/connection_adapters/sqlite3_adapter.rb
|
|
194
|
+
- lib/schema_monkey/core_extensions/active_record/connection_adapters/table_definition.rb
|
|
195
|
+
- lib/schema_monkey/core_extensions/active_record/migration/command_recorder.rb
|
|
196
|
+
- lib/schema_monkey/core_extensions/active_record/schema_dumper.rb
|
|
197
|
+
- lib/schema_monkey/core_extensions/middleware.rb
|
|
198
|
+
- lib/schema_monkey/tool.rb
|
|
199
|
+
- lib/schema_monkey/tool/client.rb
|
|
200
|
+
- lib/schema_monkey/tool/errors.rb
|
|
201
|
+
- lib/schema_monkey/tool/module.rb
|
|
202
|
+
- lib/schema_monkey/tool/monkey.rb
|
|
203
|
+
- lib/schema_monkey/tool/rake.rb
|
|
204
|
+
- lib/schema_monkey/tool/stack.rb
|
|
205
|
+
- lib/schema_monkey/tool/tasks/insert.rake
|
|
215
206
|
- lib/schema_monkey/version.rb
|
|
216
207
|
- schema_dev.yml
|
|
217
208
|
- schema_monkey.gemspec
|
|
218
209
|
- spec/connection_spec.rb
|
|
210
|
+
- spec/middleware_spec.rb
|
|
219
211
|
- spec/rake_spec.rb
|
|
220
212
|
- spec/spec_helper.rb
|
|
221
213
|
homepage: https://github.com/SchemaPlus/schema_monkey
|
|
@@ -245,5 +237,6 @@ summary: Provides an internal API and module inclusion protocol to facilitate ad
|
|
|
245
237
|
features to ActiveRecord
|
|
246
238
|
test_files:
|
|
247
239
|
- spec/connection_spec.rb
|
|
240
|
+
- spec/middleware_spec.rb
|
|
248
241
|
- spec/rake_spec.rb
|
|
249
242
|
- spec/spec_helper.rb
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
2
|
-
module ActiveRecord
|
|
3
|
-
module ConnectionAdapters
|
|
4
|
-
module PostgresqlAdapter
|
|
5
|
-
|
|
6
|
-
def self.included(base)
|
|
7
|
-
base.class_eval do
|
|
8
|
-
alias_method_chain :exec_cache, :schema_monkey
|
|
9
|
-
alias_method_chain :indexes, :schema_monkey
|
|
10
|
-
end
|
|
11
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::SchemaStatements, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Reference
|
|
12
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Column
|
|
13
|
-
SchemaMonkey.include_once ::ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements, SchemaMonkey::ActiveRecord::ConnectionAdapters::SchemaStatements::Index
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def exec_cache_with_schema_monkey(sql, name, binds)
|
|
17
|
-
Middleware::Query::ExecCache.start connection: self, sql: sql, name: name, binds: binds do |env|
|
|
18
|
-
exec_cache_without_schema_monkey(env.sql, env.name, env.binds)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def indexes_with_schema_monkey(table_name, query_name=nil)
|
|
23
|
-
Middleware::Query::Indexes.start connection: self, table_name: table_name, query_name: query_name, index_definitions: [] do |env|
|
|
24
|
-
env.index_definitions += indexes_without_schema_monkey env.table_name, env.query_name
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
module SchemaMonkey
|
|
2
|
-
module Middleware
|
|
3
|
-
|
|
4
|
-
class Base
|
|
5
|
-
def initialize(app)
|
|
6
|
-
@app = app
|
|
7
|
-
end
|
|
8
|
-
def continue(env)
|
|
9
|
-
@app.call env
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
module Stack
|
|
14
|
-
def stack
|
|
15
|
-
@stack ||= ::Middleware::Builder.new do
|
|
16
|
-
use Root
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def append(middleware)
|
|
21
|
-
stack.insert_before(Root, middleware)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def prepend(middleware)
|
|
25
|
-
stack.insert(0, middleware)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def start(*args, &block)
|
|
29
|
-
env = self.const_get(:Env).new(*args)
|
|
30
|
-
env.instance_variable_set('@root', block)
|
|
31
|
-
stack.call(env)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
class Root < Base
|
|
35
|
-
def call(env)
|
|
36
|
-
env.instance_variable_get('@root').call(env)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
module Query
|
|
42
|
-
module ExecCache
|
|
43
|
-
extend Stack
|
|
44
|
-
Env = KeyStruct[:connection, :sql, :name, :binds]
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
module Tables
|
|
48
|
-
extend Stack
|
|
49
|
-
# :database and :like are only for mysql
|
|
50
|
-
# :table_name is only for sqlite3
|
|
51
|
-
Env = KeyStruct[:connection, :query_name, :table_name, :database, :like, :tables]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
module Indexes
|
|
55
|
-
extend Stack
|
|
56
|
-
Env = KeyStruct[:connection, :table_name, :query_name, :index_definitions]
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
module Migration
|
|
61
|
-
|
|
62
|
-
module Column
|
|
63
|
-
extend Stack
|
|
64
|
-
Env = KeyStruct[:caller, :operation, :table_name, :column_name, :type, :options]
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
module ColumnOptionsSql
|
|
68
|
-
extend Stack
|
|
69
|
-
Env = KeyStruct[:caller, :connection, :sql, :options]
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
module Index
|
|
73
|
-
extend Stack
|
|
74
|
-
Env = KeyStruct[:caller, :operation, :table_name, :column_names, :options]
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
module IndexComponentsSql
|
|
78
|
-
extend Stack
|
|
79
|
-
Sql = KeyStruct[:name, :type, :columns, :options, :algorithm, :using]
|
|
80
|
-
Env = KeyStruct[:connection, :table_name, :column_names, :options, sql: Sql.new]
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
module Dumper
|
|
86
|
-
module Extensions
|
|
87
|
-
extend Stack
|
|
88
|
-
Env = KeyStruct[:dumper, :connection, :dump, :extensions]
|
|
89
|
-
end
|
|
90
|
-
module Tables
|
|
91
|
-
extend Stack
|
|
92
|
-
Env = KeyStruct[:dumper, :connection, :dump]
|
|
93
|
-
end
|
|
94
|
-
module Table
|
|
95
|
-
extend Stack
|
|
96
|
-
Env = KeyStruct[:dumper, :connection, :dump, :table]
|
|
97
|
-
end
|
|
98
|
-
module Indexes
|
|
99
|
-
extend Stack
|
|
100
|
-
Env = KeyStruct[:dumper, :connection, :dump, :table]
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
module Model
|
|
105
|
-
module Columns
|
|
106
|
-
extend Stack
|
|
107
|
-
Env = KeyStruct[:model, :columns]
|
|
108
|
-
end
|
|
109
|
-
module ResetColumnInformation
|
|
110
|
-
extend Stack
|
|
111
|
-
Env = KeyStruct[:model]
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
end
|
|
117
|
-
end
|