schema_monkey 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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