schema_monkey 2.0.0 → 2.0.1
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 +24 -18
- data/gemfiles/Gemfile.base +0 -4
- data/lib/schema_monkey.rb +2 -2
- data/lib/schema_monkey/client.rb +1 -2
- data/lib/schema_monkey/monkey.rb +2 -2
- data/lib/schema_monkey/stack.rb +10 -10
- data/lib/schema_monkey/version.rb +1 -1
- data/schema_monkey.gemspec +2 -2
- data/spec/active_record_spec.rb +15 -10
- data/spec/middleware_spec.rb +8 -0
- metadata +5 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2ba91ff751129e56965c986ca35a5ca8c7a4996
|
4
|
+
data.tar.gz: 48fac590947b7de42eeb8137eac0ec79639eb544
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f989b848d4dd7b49d970c7e65faa96ddf503a05c24463d0e8737f3f136fd0e1175181d65b649964d66ac9aae0f5977f039cb5b5d7b803e73bf448975899e92e
|
7
|
+
data.tar.gz: 8674917f2c77a10d16d1d52c9b54ed2bafc4386f869588d401fdbece2ae731b1e1a2787c6587e0c98c04caa11363b35d058f9fac772b1bd7de1ab240279513ff
|
data/README.md
CHANGED
@@ -35,8 +35,8 @@ SchemaMonkey works with the notion of a "client" -- which is a module containini
|
|
35
35
|
|
36
36
|
```ruby
|
37
37
|
require 'schema_monkey'
|
38
|
-
require 'other-client1' #
|
39
|
-
require 'other-client2' # as needed
|
38
|
+
require 'other-client1' # make sure clients you depend on are registered
|
39
|
+
require 'other-client2' # first, if/as needed.
|
40
40
|
|
41
41
|
module MyClient
|
42
42
|
|
@@ -51,7 +51,7 @@ module MyClient
|
|
51
51
|
# middleware stack modules, if any
|
52
52
|
#
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
end
|
56
56
|
|
57
57
|
SchemaMonkey.register MyClient # <--- That's it! No configuration needed
|
@@ -86,19 +86,19 @@ require 'schema_monkey'
|
|
86
86
|
module PracticalJoker
|
87
87
|
module ActiveRecord
|
88
88
|
module Base
|
89
|
-
|
89
|
+
|
90
90
|
def save(*args)
|
91
91
|
raise "April Fools!" if Time.now.yday == 31
|
92
92
|
super
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
module ClassMethods
|
96
96
|
def columns
|
97
97
|
raise "Boo!" if Time.now.yday == 304
|
98
98
|
super
|
99
99
|
end
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
@@ -107,11 +107,11 @@ end
|
|
107
107
|
SchemaMonkey.register PracticalJoker
|
108
108
|
```
|
109
109
|
|
110
|
-
SchemaMonkey inserts each submodule of `MyClient::ActiveRecord` into the corresponding module of ActiveRecord, with `ClassMethods` inserted as class methods.
|
110
|
+
SchemaMonkey inserts each submodule of `MyClient::ActiveRecord` into the corresponding module of ActiveRecord, with `ClassMethods` inserted as class methods.
|
111
111
|
|
112
112
|
This works for arbitrary submodule paths, such as `MyClient::ActiveRecord::ConnectionAdapters::TableDefinition`. SchemaMonkey will raise an error if the client defines a module that does not have a corresponding ActiveRecord module.
|
113
113
|
|
114
|
-
Notice that insertion is done using
|
114
|
+
Notice that insertion is done using `Module.prepend`, so that client modules can override existing methods and use `super`.
|
115
115
|
|
116
116
|
### DBMS-specific insertion
|
117
117
|
|
@@ -126,7 +126,7 @@ module MyClient
|
|
126
126
|
module Sqlite3
|
127
127
|
module TableDefinition
|
128
128
|
#
|
129
|
-
# SQLite3-specific enhancements to
|
129
|
+
# SQLite3-specific enhancements to
|
130
130
|
# ActiveRecord::ConnectionAdapters::TableDefinition
|
131
131
|
#
|
132
132
|
end
|
@@ -145,11 +145,11 @@ The dbms name component can be anywhere in the module path after `MyClient::Acti
|
|
145
145
|
|
146
146
|
* However, if the client module defines a module method `self.included` then SchemaMonkey will use `include` for a module and `singleton_class.include` for a ClassMethods module -- and Ruby will of course call that method.
|
147
147
|
|
148
|
-
Note that in the case of a ClassMethods module, when Ruby calls `self.prepended` or `self.included`, it will pass the singleton class. For convience SchemaMonkey will also call `self.extended` if defined passing it the ActiveRecord module itself, just as Ruby would if `extend` were used.
|
148
|
+
Note that in the case of a ClassMethods module, when Ruby calls `self.prepended` or `self.included`, it will pass the singleton class. For convience SchemaMonkey will also call `self.extended` if defined, passing it the ActiveRecord module itself, just as Ruby would if `extend` were used.
|
149
149
|
|
150
|
-
## Middleware
|
150
|
+
## Middleware Modules
|
151
151
|
|
152
|
-
SchemaMonkey provides a convention-based front end to using [
|
152
|
+
SchemaMonkey provides a convention-based front end to using [modware](https://github.com/ronen/modware) middleware stacks.
|
153
153
|
|
154
154
|
SchemaMonkey uses Ruby modules to organize the stacks: Each stack is contained in a submodule of `SchemaMonkey::Middleware`
|
155
155
|
|
@@ -173,18 +173,20 @@ This defines a stack available at `SchemaMonkey::Middleware::Index::Exists`. Yo
|
|
173
173
|
|
174
174
|
SchemaMonkey will raise an error if a stack had already been defined there.
|
175
175
|
|
176
|
-
The defined module has a module method `start` that delegates to `Modware::Stack.start`. Here's an example of using the above stack as a wrapper around ActiveRecord's `index_exists?` method:
|
176
|
+
The defined stack module has a module method `start` that delegates to `Modware::Stack.start`. Here's an example of using the above stack as a wrapper around ActiveRecord's `index_exists?` method:
|
177
177
|
|
178
178
|
```ruby
|
179
179
|
module MyClient
|
180
180
|
module ActiveRecord
|
181
181
|
module ConnectionAdapters
|
182
182
|
module SchemaStatements
|
183
|
+
|
183
184
|
def index_exists?(table_name, column_name, options = {})
|
184
185
|
SchemaMonkey::Middleware::Index::Exists.start(connection: self, table_name: table_name, column_name: column_name, options: options) { |env|
|
185
186
|
env.result = super env.table_name, env.column_name, env.options
|
186
187
|
}.result
|
187
188
|
end
|
189
|
+
|
188
190
|
end
|
189
191
|
end
|
190
192
|
end
|
@@ -220,11 +222,11 @@ end
|
|
220
222
|
SchemaMonkey.register(UColumnImpliesUnique)
|
221
223
|
```
|
222
224
|
|
223
|
-
SchemaMonkey uses the module `MyLaterClient::Middleware::Index::Exists` as [
|
225
|
+
SchemaMonkey uses the module `MyLaterClient::Middleware::Index::Exists` as [modware](https://github.com/ronen/modware) middleware for the corresponding stack. The middleware module can define middleware methods `before`, `arround`, `after`, or `implementation` as per [modware](https://github.com/ronen/modware)
|
224
226
|
|
225
227
|
Note that the distinguishing feature between defining and using a stack is whether `Env` is defined.
|
226
228
|
|
227
|
-
|
229
|
+
|
228
230
|
|
229
231
|
|
230
232
|
## Compatibility
|
@@ -246,8 +248,10 @@ the standard protocol: fork, feature branch, develop, push, and issue pull reque
|
|
246
248
|
|
247
249
|
Some things to know about to help you develop and test:
|
248
250
|
|
251
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
|
252
|
+
<!-- These lines are auto-inserted from a schema_dev template -->
|
249
253
|
* **schema_dev**: SchemaMonkey uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
|
250
|
-
facilitate running rspec tests on the matrix of ruby,
|
254
|
+
facilitate running rspec tests on the matrix of ruby, activerecord, and database
|
251
255
|
versions that the gem supports, both locally and on
|
252
256
|
[travis-ci](http://travis-ci.org/SchemaPlus/schema_monkey)
|
253
257
|
|
@@ -256,8 +260,10 @@ Some things to know about to help you develop and test:
|
|
256
260
|
$ schema_dev bundle install
|
257
261
|
$ schema_dev rspec
|
258
262
|
|
259
|
-
You can also run on just one configuration at a time; For info, see `schema_dev --help` or the
|
260
|
-
[schema_dev](https://github.com/SchemaPlus/schema_dev) README.
|
263
|
+
You can also run on just one configuration at a time; For info, see `schema_dev --help` or the [schema_dev](https://github.com/SchemaPlus/schema_dev) README.
|
261
264
|
|
262
265
|
The matrix of configurations is specified in `schema_dev.yml` in
|
263
266
|
the project root.
|
267
|
+
|
268
|
+
|
269
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
|
data/gemfiles/Gemfile.base
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
gemspec :path => File.expand_path('..', __FILE__)
|
3
3
|
|
4
|
-
platform :ruby do
|
5
|
-
gem "byebug" if RUBY_VERSION > "2"
|
6
|
-
end
|
7
|
-
|
8
4
|
File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
|
data/lib/schema_monkey.rb
CHANGED
@@ -11,7 +11,7 @@ require_relative "schema_monkey/monkey"
|
|
11
11
|
require_relative "schema_monkey/stack"
|
12
12
|
require_relative 'schema_monkey/rake'
|
13
13
|
|
14
|
-
#
|
14
|
+
#
|
15
15
|
# Middleware contents will be created dynamically
|
16
16
|
#
|
17
17
|
module SchemaMonkey
|
@@ -20,7 +20,7 @@ module SchemaMonkey
|
|
20
20
|
end
|
21
21
|
|
22
22
|
#
|
23
|
-
#
|
23
|
+
#
|
24
24
|
#
|
25
25
|
module SchemaMonkey
|
26
26
|
|
data/lib/schema_monkey/client.rb
CHANGED
@@ -16,7 +16,6 @@ module SchemaMonkey
|
|
16
16
|
def insert_active_record(dbm: nil)
|
17
17
|
# Kernel.warn "--- inserting active_record for #{@root}, dbm=#{dbm.inspect}"
|
18
18
|
find_modules(:ActiveRecord, dbm: dbm).each do |mod|
|
19
|
-
next if mod.is_a? Class
|
20
19
|
relative_path = canonicalize_path(mod, :ActiveRecord, dbm)
|
21
20
|
ActiveRecord.insert(relative_path, mod)
|
22
21
|
end
|
@@ -35,7 +34,7 @@ module SchemaMonkey
|
|
35
34
|
path = mod.to_s.sub(/^#{@root}::#{base}::/, '')
|
36
35
|
if dbm
|
37
36
|
path = path.split('::')
|
38
|
-
if (i = path.find_index(&it =~ /\b#{dbm}\b/i)) # delete first occurence
|
37
|
+
if (i = path.find_index(&it =~ /\b#{dbm}\b/i)) # delete first occurence
|
39
38
|
path.delete_at i
|
40
39
|
end
|
41
40
|
path = path.join('::').gsub(/#{dbm}/i, dbm.to_s) # canonicalize case for things like PostgreSQLAdapter
|
data/lib/schema_monkey/monkey.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module SchemaMonkey
|
2
2
|
|
3
|
-
# The main manager for the monkey patches. Singleton instance
|
3
|
+
# The main manager for the monkey patches. Singleton instance
|
4
4
|
# created by SchemaMonkey.monkey
|
5
5
|
|
6
6
|
class Monkey
|
@@ -11,7 +11,7 @@ module SchemaMonkey
|
|
11
11
|
@clients = []
|
12
12
|
@inserted = nil
|
13
13
|
@inserted_dbm = nil
|
14
|
-
Module.insert ::ActiveRecord::ConnectionAdapters::AbstractAdapter, SchemaMonkey::ActiveRecord::ConnectionAdapters::AbstractAdapter
|
14
|
+
Module.insert ::ActiveRecord::ConnectionAdapters::AbstractAdapter, SchemaMonkey::ActiveRecord::ConnectionAdapters::AbstractAdapter
|
15
15
|
end
|
16
16
|
|
17
17
|
def register(mod)
|
data/lib/schema_monkey/stack.rb
CHANGED
@@ -3,8 +3,8 @@ module SchemaMonkey
|
|
3
3
|
def self.insert(path, mod)
|
4
4
|
env = Module.const_lookup(mod, "Env") || Module.const_lookup(mod, "ENV")
|
5
5
|
return unless env or Modware.is_middleware?(mod)
|
6
|
-
|
7
|
-
|
6
|
+
stack_holder = env ? create(path, env) : get(path)
|
7
|
+
stack_holder.stack.add(mod)
|
8
8
|
rescue MiddlewareError => err
|
9
9
|
raise MiddlewareError, "#{mod}: #{err.message}"
|
10
10
|
end
|
@@ -12,22 +12,22 @@ module SchemaMonkey
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def self.create(path, env)
|
15
|
-
if
|
16
|
-
raise MiddlewareError, "stack #{
|
15
|
+
if mod = get(path, err: false)
|
16
|
+
raise MiddlewareError, "stack #{mod} is already defined"
|
17
17
|
end
|
18
|
-
Module.mkpath(SchemaMonkey::Middleware, path).tap { |
|
19
|
-
|
20
|
-
|
18
|
+
Module.mkpath(SchemaMonkey::Middleware, path).tap { |mod|
|
19
|
+
mod.send :extend, Stack::StackHolder
|
20
|
+
mod.send :stack=, Modware::Stack.new(env: env)
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.get(path, err: true)
|
25
|
-
|
26
|
-
return
|
25
|
+
mod = Module.const_lookup SchemaMonkey::Middleware, path
|
26
|
+
return mod if mod and mod.is_a? Stack::StackHolder
|
27
27
|
raise MiddlewareError, "No stack #{SchemaMonkey::Middleware}::#{path}" if err
|
28
28
|
end
|
29
29
|
|
30
|
-
module
|
30
|
+
module StackHolder
|
31
31
|
attr_reader :stack
|
32
32
|
|
33
33
|
def start(env, &block)
|
data/schema_monkey.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = SchemaMonkey::VERSION
|
9
9
|
spec.authors = ["ronen barzel"]
|
10
10
|
spec.email = ["ronen@barzel.org"]
|
11
|
-
spec.summary = %q{Provides
|
12
|
-
spec.description = %q{Provides
|
11
|
+
spec.summary = %q{Provides a module insertion protocol to facilitate adding features to ActiveRecord}
|
12
|
+
spec.description = %q{Provides a module insertion protocol to facilitate adding features to ActiveRecord}
|
13
13
|
spec.homepage = "https://github.com/SchemaPlus/schema_monkey"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
data/spec/active_record_spec.rb
CHANGED
@@ -4,7 +4,7 @@ $client_count = 0
|
|
4
4
|
|
5
5
|
describe SchemaMonkey::ActiveRecord do
|
6
6
|
|
7
|
-
|
7
|
+
When(:result) {
|
8
8
|
SchemaMonkey.register(client)
|
9
9
|
SchemaMonkey.insert
|
10
10
|
ActiveRecord::Base.establish_connection :schema_dev
|
@@ -16,23 +16,23 @@ describe SchemaMonkey::ActiveRecord do
|
|
16
16
|
|
17
17
|
[:prepend, :include].each do |mode|
|
18
18
|
|
19
|
-
context "#{mode} general module"+suffix do
|
20
|
-
|
21
|
-
|
19
|
+
context "with #{mode} general module"+suffix do
|
20
|
+
Given(:client) { make_client('ConnectionAdapters::SchemaStatements', mode: mode, class_methods: class_methods) }
|
21
|
+
Then { expect_inserted(ActiveRecord::ConnectionAdapters::SchemaStatements, client.module, mode, class_methods) }
|
22
22
|
end
|
23
23
|
|
24
24
|
SchemaMonkey::DBMS.each do |dbm|
|
25
25
|
|
26
|
-
context "#{mode} #{dbm} module"+suffix do
|
27
|
-
|
26
|
+
context "with #{mode} #{dbm} module"+suffix do
|
27
|
+
Given(:client) { make_client("ConnectionAdapters::#{dbm}::SchemaStatements", mode: mode, class_methods: class_methods) }
|
28
28
|
|
29
29
|
SchemaMonkey::DBMS.each do |loaded_dbm|
|
30
30
|
|
31
|
-
context "
|
31
|
+
context "if using #{loaded_dbm}", loaded_dbm.to_s.downcase.to_sym => :only do
|
32
32
|
if dbm == loaded_dbm
|
33
|
-
|
33
|
+
Then { expect_inserted(ActiveRecord::ConnectionAdapters::SchemaStatements, client.module, mode, class_methods) }
|
34
34
|
else
|
35
|
-
|
35
|
+
Then { expect_not_inserted(ActiveRecord::ConnectionAdapters::SchemaStatements, client.module, class_methods) }
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -42,6 +42,11 @@ describe SchemaMonkey::ActiveRecord do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
context "with invalid module" do
|
46
|
+
Given(:client) { make_client('ConnectionAdapters::NoSuchModule') }
|
47
|
+
Then { expect(result).to have_failed(SchemaMonkey::InsertionError) }
|
48
|
+
end
|
49
|
+
|
45
50
|
private
|
46
51
|
|
47
52
|
def expect_inserted(base, mod, mode, class_methods)
|
@@ -59,7 +64,7 @@ describe SchemaMonkey::ActiveRecord do
|
|
59
64
|
expect(base.ancestors).not_to include mod
|
60
65
|
end
|
61
66
|
|
62
|
-
def make_client(path, mode
|
67
|
+
def make_client(path, mode: nil, class_methods: nil)
|
63
68
|
name = "TestActiveRecord#{$client_count}"
|
64
69
|
$client_count += 1
|
65
70
|
Object.send :remove_const, name if Object.const_defined? name
|
data/spec/middleware_spec.rb
CHANGED
@@ -45,6 +45,14 @@ describe SchemaMonkey::Middleware do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
context "with module but no stack registered" do
|
49
|
+
context "if register client1" do
|
50
|
+
Given { SchemaMonkey::Module.mkpath SchemaMonkey::Middleware, "Group::Stack" }
|
51
|
+
Given { SchemaMonkey.register make_client(1) }
|
52
|
+
Then { expect(insertion).to have_failed(SchemaMonkey::MiddlewareError, /no stack/i) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
48
56
|
|
49
57
|
def make_definition
|
50
58
|
Module.new.tap(&it.module_eval(<<-END))
|
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: 2.0.
|
4
|
+
version: 2.0.1
|
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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -150,8 +150,8 @@ dependencies:
|
|
150
150
|
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
-
description: Provides
|
154
|
-
|
153
|
+
description: Provides a module insertion protocol to facilitate adding features to
|
154
|
+
ActiveRecord
|
155
155
|
email:
|
156
156
|
- ronen@barzel.org
|
157
157
|
executables: []
|
@@ -209,8 +209,7 @@ rubyforge_project:
|
|
209
209
|
rubygems_version: 2.2.2
|
210
210
|
signing_key:
|
211
211
|
specification_version: 4
|
212
|
-
summary: Provides
|
213
|
-
features to ActiveRecord
|
212
|
+
summary: Provides a module insertion protocol to facilitate adding features to ActiveRecord
|
214
213
|
test_files:
|
215
214
|
- spec/active_record_spec.rb
|
216
215
|
- spec/connection_spec.rb
|