schema_monkey 1.0.1 → 2.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +0 -1
  4. data/Gemfile +2 -0
  5. data/README.md +204 -28
  6. data/lib/schema_monkey.rb +30 -17
  7. data/lib/schema_monkey/active_record.rb +25 -0
  8. data/lib/schema_monkey/client.rb +65 -0
  9. data/lib/schema_monkey/errors.rb +6 -0
  10. data/lib/schema_monkey/{tool/module.rb → module.rb} +10 -7
  11. data/lib/schema_monkey/monkey.rb +31 -0
  12. data/lib/schema_monkey/{tool/rake.rb → rake.rb} +1 -1
  13. data/lib/schema_monkey/stack.rb +44 -0
  14. data/lib/schema_monkey/{tool/tasks → tasks}/insert.rake +0 -0
  15. data/lib/schema_monkey/version.rb +1 -1
  16. data/schema_dev.yml +0 -1
  17. data/schema_monkey.gemspec +2 -2
  18. data/spec/active_record_spec.rb +75 -0
  19. data/spec/middleware_spec.rb +0 -7
  20. data/spec/spec_helper.rb +2 -2
  21. metadata +18 -41
  22. data/lib/schema_monkey/core_extensions.rb +0 -23
  23. data/lib/schema_monkey/core_extensions/active_record/base.rb +0 -31
  24. data/lib/schema_monkey/core_extensions/active_record/connection_adapters/abstract_adapter.rb +0 -38
  25. data/lib/schema_monkey/core_extensions/active_record/connection_adapters/mysql2_adapter.rb +0 -31
  26. data/lib/schema_monkey/core_extensions/active_record/connection_adapters/postgresql_adapter.rb +0 -30
  27. data/lib/schema_monkey/core_extensions/active_record/connection_adapters/schema_statements.rb +0 -83
  28. data/lib/schema_monkey/core_extensions/active_record/connection_adapters/sqlite3_adapter.rb +0 -33
  29. data/lib/schema_monkey/core_extensions/active_record/connection_adapters/table_definition.rb +0 -42
  30. data/lib/schema_monkey/core_extensions/active_record/migration/command_recorder.rb +0 -19
  31. data/lib/schema_monkey/core_extensions/active_record/schema_dumper.rb +0 -227
  32. data/lib/schema_monkey/core_extensions/middleware.rb +0 -62
  33. data/lib/schema_monkey/tool.rb +0 -43
  34. data/lib/schema_monkey/tool/client.rb +0 -67
  35. data/lib/schema_monkey/tool/errors.rb +0 -4
  36. data/lib/schema_monkey/tool/monkey.rb +0 -46
  37. data/lib/schema_monkey/tool/stack.rb +0 -90
@@ -0,0 +1,6 @@
1
+ module SchemaMonkey
2
+ class MiddlewareError < Exception
3
+ end
4
+ class InsertionError < Exception
5
+ end
6
+ end
@@ -1,9 +1,13 @@
1
- module SchemaMonkey::Tool
1
+ module SchemaMonkey
2
2
  module Module
3
3
  extend self
4
4
 
5
- def include_once(base, mod)
6
- base.send(:include, mod) unless base.include? mod
5
+ def insert(base, mod)
6
+ if mod.respond_to? :included
7
+ base.send(:include, mod) unless base.include? mod
8
+ else
9
+ base.send(:prepend, mod)
10
+ end
7
11
  end
8
12
 
9
13
  # ruby 2.* supports mod.const_get("Component::Path") but ruby 1.9.3
@@ -20,13 +24,12 @@ module SchemaMonkey::Tool
20
24
  mod
21
25
  end
22
26
 
23
- def descendants(mod, opts={})
24
- opts = opts.keyword_args(can_load: nil)
27
+ def descendants(mod, can_load: nil)
25
28
  consts, auto = mod.constants.group_by{|c| !!mod.autoload?(c)}.values_at(false, true)
26
29
  consts ||= []
27
- consts += auto.select &it.to_s =~ opts.can_load if opts.can_load and auto
30
+ consts += auto.select &it.to_s =~ can_load if can_load and auto
28
31
  children = consts.map{|c| mod.const_get(c) }.select &it.is_a?(::Module)
29
- children + children.flat_map {|c| descendants(c, can_load: opts.can_load) }
32
+ children + children.flat_map {|c| descendants(c, can_load: can_load) }
30
33
  end
31
34
 
32
35
  def mkpath(mod, path)
@@ -0,0 +1,31 @@
1
+ module SchemaMonkey
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
+ @inserted = nil
13
+ @inserted_dbm = nil
14
+ Module.insert ::ActiveRecord::ConnectionAdapters::AbstractAdapter, SchemaMonkey::ActiveRecord::ConnectionAdapters::AbstractAdapter
15
+ end
16
+
17
+ def register(mod)
18
+ client = Client.new(mod)
19
+ clients << client
20
+ client.insert if @inserted
21
+ client.insert(dbm: @inserted_dbm) if @inserted_dbm
22
+ end
23
+
24
+ def insert(dbm: nil)
25
+ clients.each &it.insert(dbm: dbm)
26
+ @inserted = true
27
+ @inserted_dbm = dbm if dbm
28
+ end
29
+
30
+ end
31
+ end
@@ -1,4 +1,4 @@
1
- module SchemaMonkey::Tool
1
+ module SchemaMonkey
2
2
  module Rake
3
3
  TASKS_PATH = Pathname.new(__FILE__).dirname + "tasks"
4
4
 
@@ -0,0 +1,44 @@
1
+ module SchemaMonkey
2
+ module Stack
3
+ def self.insert(path, mod)
4
+ env = Module.const_lookup(mod, "Env") || Module.const_lookup(mod, "ENV")
5
+ return unless env or Modware.is_middleware?(mod)
6
+ stack = env ? create(path, env) : get(path)
7
+ stack.stack.add(mod)
8
+ rescue MiddlewareError => err
9
+ raise MiddlewareError, "#{mod}: #{err.message}"
10
+ end
11
+
12
+ private
13
+
14
+ def self.create(path, env)
15
+ if stack = get(path, err: false)
16
+ raise MiddlewareError, "stack #{stack} is already defined"
17
+ end
18
+ Module.mkpath(SchemaMonkey::Middleware, path).tap { |stack|
19
+ stack.send :extend, Stack::StartMethod
20
+ stack.send :stack=, Modware::Stack.new(env: env)
21
+ }
22
+ end
23
+
24
+ def self.get(path, err: true)
25
+ stack = Module.const_lookup SchemaMonkey::Middleware, path
26
+ return stack if stack
27
+ raise MiddlewareError, "No stack #{SchemaMonkey::Middleware}::#{path}" if err
28
+ end
29
+
30
+ module StartMethod
31
+ attr_reader :stack
32
+
33
+ def start(env, &block)
34
+ stack.start(env, &block)
35
+ end
36
+
37
+ private
38
+
39
+ def stack=(stack)
40
+ @stack = stack
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module SchemaMonkey
2
- VERSION = "1.0.1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,5 +1,4 @@
1
1
  ruby:
2
- - 1.9.3
3
2
  - 2.1.5
4
3
  activerecord:
5
4
  - 4.2
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.required_ruby_version = ">= 2.1.0"
21
22
  spec.add_dependency "activerecord", "~> 4.2"
22
- spec.add_dependency "hash_keyword_args"
23
23
  spec.add_dependency "its-it"
24
- spec.add_dependency "key_struct"
24
+ spec.add_dependency "modware", "~> 0.1"
25
25
 
26
26
  spec.add_development_dependency "bundler", "~> 1.7"
27
27
  spec.add_development_dependency "rake", "~> 10.0"
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ $client_count = 0
4
+
5
+ describe SchemaMonkey::ActiveRecord do
6
+
7
+ before(:each) {
8
+ SchemaMonkey.register(client)
9
+ SchemaMonkey.insert
10
+ ActiveRecord::Base.establish_connection :schema_dev
11
+ ActiveRecord::Base.connection
12
+ }
13
+
14
+ [false, true].each do |class_methods|
15
+ suffix = class_methods ? " class methods" : ""
16
+
17
+ [:prepend, :include].each do |mode|
18
+
19
+ context "#{mode} general module"+suffix do
20
+ let(:client) { make_client('ConnectionAdapters::SchemaStatements', mode: mode, class_methods: class_methods) }
21
+ it { expect_inserted(ActiveRecord::ConnectionAdapters::SchemaStatements, client.module, mode, class_methods) }
22
+ end
23
+
24
+ SchemaMonkey::DBMS.each do |dbm|
25
+
26
+ context "#{mode} #{dbm} module"+suffix do
27
+ let(:client) { make_client("ConnectionAdapters::#{dbm}::SchemaStatements", mode: mode, class_methods: class_methods) }
28
+
29
+ SchemaMonkey::DBMS.each do |loaded_dbm|
30
+
31
+ context "when #{loaded_dbm}", loaded_dbm.to_s.downcase.to_sym => :only do
32
+ if dbm == loaded_dbm
33
+ it { expect_inserted(ActiveRecord::ConnectionAdapters::SchemaStatements, client.module, mode, class_methods) }
34
+ else
35
+ it { expect_not_inserted(ActiveRecord::ConnectionAdapters::SchemaStatements, client.module, class_methods) }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def expect_inserted(base, mod, mode, class_methods)
48
+ base = base.singleton_class if class_methods
49
+ actual = base.ancestors.select{|a| [base, mod].include? a}
50
+ expected = case mode
51
+ when :prepend then [mod, base]
52
+ when :include then [base, mod]
53
+ end
54
+ expect(actual).to eq expected
55
+ end
56
+
57
+ def expect_not_inserted(base, mod, class_methods)
58
+ base = base.singleton_class if class_methods
59
+ expect(base.ancestors).not_to include mod
60
+ end
61
+
62
+ def make_client(path, mode:, class_methods: nil)
63
+ name = "TestActiveRecord#{$client_count}"
64
+ $client_count += 1
65
+ Object.send :remove_const, name if Object.const_defined? name
66
+ Object.const_set name, Module.new.tap { |client|
67
+ path += "::ClassMethods" if class_methods
68
+ sub = SchemaMonkey::Module.mkpath(client, 'ActiveRecord::' + path)
69
+ client.singleton_class.send(:define_method, :module) { sub }
70
+ sub.singleton_class.send(:define_method, :included) {|base|} if mode == :include
71
+ }
72
+ end
73
+
74
+
75
+ end
@@ -10,13 +10,6 @@ describe SchemaMonkey::Middleware do
10
10
 
11
11
  Then { expect(defined?(SchemaMonkey::Middleware::Group::Stack)).to be_truthy }
12
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
13
  context "when start with inline implementation" do
21
14
 
22
15
  When(:env) { SchemaMonkey::Middleware::Group::Stack.start result: [] { |env| env.result << :inline } }
@@ -19,8 +19,8 @@ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
19
19
 
20
20
  RSpec.configure do |config|
21
21
  config.warnings = true
22
- config.after(:each) do
23
- SchemaMonkey::Tool.reset_for_rspec
22
+ config.before(:each) do
23
+ SchemaMonkey.reset_for_rspec
24
24
  end
25
25
  end
26
26
 
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: 1.0.1
4
+ version: 2.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-03 00:00:00.000000000 Z
11
+ date: 2015-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.2'
27
- - !ruby/object:Gem::Dependency
28
- name: hash_keyword_args
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: its-it
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -53,19 +39,19 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
- name: key_struct
42
+ name: modware
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - ">="
45
+ - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '0'
47
+ version: '0.1'
62
48
  type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - ">="
52
+ - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '0'
54
+ version: '0.1'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: bundler
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -184,28 +170,18 @@ files:
184
170
  - gemfiles/activerecord-4.2/Gemfile.postgresql
185
171
  - gemfiles/activerecord-4.2/Gemfile.sqlite3
186
172
  - lib/schema_monkey.rb
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
173
+ - lib/schema_monkey/active_record.rb
174
+ - lib/schema_monkey/client.rb
175
+ - lib/schema_monkey/errors.rb
176
+ - lib/schema_monkey/module.rb
177
+ - lib/schema_monkey/monkey.rb
178
+ - lib/schema_monkey/rake.rb
179
+ - lib/schema_monkey/stack.rb
180
+ - lib/schema_monkey/tasks/insert.rake
206
181
  - lib/schema_monkey/version.rb
207
182
  - schema_dev.yml
208
183
  - schema_monkey.gemspec
184
+ - spec/active_record_spec.rb
209
185
  - spec/connection_spec.rb
210
186
  - spec/middleware_spec.rb
211
187
  - spec/rake_spec.rb
@@ -222,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
222
198
  requirements:
223
199
  - - ">="
224
200
  - !ruby/object:Gem::Version
225
- version: '0'
201
+ version: 2.1.0
226
202
  required_rubygems_version: !ruby/object:Gem::Requirement
227
203
  requirements:
228
204
  - - ">="
@@ -236,6 +212,7 @@ specification_version: 4
236
212
  summary: Provides an internal API and module inclusion protocol to facilitate adding
237
213
  features to ActiveRecord
238
214
  test_files:
215
+ - spec/active_record_spec.rb
239
216
  - spec/connection_spec.rb
240
217
  - spec/middleware_spec.rb
241
218
  - spec/rake_spec.rb
@@ -1,23 +0,0 @@
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,31 +0,0 @@
1
- module SchemaMonkey::CoreExtensions
2
- module ActiveRecord
3
-
4
- module Base
5
- def self.included(base)
6
- base.extend(ClassMethods)
7
- end
8
-
9
- module ClassMethods
10
- def self.extended(base)
11
- class << base
12
- alias_method_chain :columns, :schema_monkey
13
- alias_method_chain :reset_column_information, :schema_monkey
14
- end
15
- end
16
-
17
- def columns_with_schema_monkey
18
- SchemaMonkey::Middleware::Model::Columns.start(model: self, columns: []) { |env|
19
- env.columns += columns_without_schema_monkey
20
- }.columns
21
- end
22
-
23
- def reset_column_information_with_schema_monkey
24
- SchemaMonkey::Middleware::Model::ResetColumnInformation.start(model: self) do |env|
25
- reset_column_information_without_schema_monkey
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,38 +0,0 @@
1
- module SchemaMonkey::CoreExtensions
2
- module ActiveRecord
3
- module ConnectionAdapters
4
- module AbstractAdapter
5
- def self.included(base) #:nodoc:
6
- base.alias_method_chain :initialize, :schema_monkey
7
- end
8
-
9
- def initialize_with_schema_monkey(*args) #:nodoc:
10
- initialize_without_schema_monkey(*args)
11
-
12
- dbm = case adapter_name
13
- when /^MySQL/i then :Mysql
14
- when 'PostgreSQL', 'PostGIS' then :PostgreSQL
15
- when 'SQLite' then :SQLite3
16
- end
17
-
18
- SchemaMonkey.insert(dbm: dbm)
19
- end
20
-
21
- module SchemaCreation
22
- def self.included(base)
23
- base.class_eval do
24
- alias_method_chain :add_column_options!, :schema_monkey
25
- public :options_include_default?
26
- end
27
- end
28
-
29
- def add_column_options_with_schema_monkey!(sql, options)
30
- SchemaMonkey::Middleware::Migration::ColumnOptionsSql.start(caller: self, connection: self.instance_variable_get('@conn'), sql: sql, options: options) { |env|
31
- add_column_options_without_schema_monkey! env.sql, env.options
32
- }.sql
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end