praxis-mapper 3.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +83 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +102 -0
- data/Guardfile +11 -0
- data/LICENSE +22 -0
- data/README.md +19 -0
- data/Rakefile +14 -0
- data/lib/praxis-mapper/config_hash.rb +40 -0
- data/lib/praxis-mapper/connection_manager.rb +102 -0
- data/lib/praxis-mapper/finalizable.rb +38 -0
- data/lib/praxis-mapper/identity_map.rb +532 -0
- data/lib/praxis-mapper/logging.rb +22 -0
- data/lib/praxis-mapper/model.rb +430 -0
- data/lib/praxis-mapper/query/base.rb +213 -0
- data/lib/praxis-mapper/query/sql.rb +183 -0
- data/lib/praxis-mapper/query_statistics.rb +46 -0
- data/lib/praxis-mapper/resource.rb +226 -0
- data/lib/praxis-mapper/support/factory_girl.rb +104 -0
- data/lib/praxis-mapper/support/memory_query.rb +34 -0
- data/lib/praxis-mapper/support/memory_repository.rb +44 -0
- data/lib/praxis-mapper/support/schema_dumper.rb +66 -0
- data/lib/praxis-mapper/support/schema_loader.rb +56 -0
- data/lib/praxis-mapper/support.rb +2 -0
- data/lib/praxis-mapper/version.rb +5 -0
- data/lib/praxis-mapper.rb +60 -0
- data/praxis-mapper.gemspec +38 -0
- data/spec/praxis-mapper/connection_manager_spec.rb +117 -0
- data/spec/praxis-mapper/identity_map_spec.rb +905 -0
- data/spec/praxis-mapper/logging_spec.rb +9 -0
- data/spec/praxis-mapper/memory_repository_spec.rb +56 -0
- data/spec/praxis-mapper/model_spec.rb +389 -0
- data/spec/praxis-mapper/query/base_spec.rb +317 -0
- data/spec/praxis-mapper/query/sql_spec.rb +184 -0
- data/spec/praxis-mapper/resource_spec.rb +154 -0
- data/spec/praxis_mapper_spec.rb +21 -0
- data/spec/spec_fixtures.rb +12 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/support/spec_models.rb +215 -0
- data/spec/support/spec_resources.rb +39 -0
- metadata +298 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
Sequel.extension :migration
|
4
|
+
|
5
|
+
module Praxis::Mapper
|
6
|
+
module Support
|
7
|
+
class SchemaLoader
|
8
|
+
|
9
|
+
attr_reader :options, :schema_root
|
10
|
+
|
11
|
+
def initialize(schema_root='.', **options)
|
12
|
+
@schema_root = Pathname.new(schema_root)
|
13
|
+
@options = options
|
14
|
+
@connection_manager = ConnectionManager.new
|
15
|
+
@repositories = Set.new
|
16
|
+
|
17
|
+
@migrations = Hash.new
|
18
|
+
|
19
|
+
@connection_manager.repositories.each do |repository_name, config|
|
20
|
+
|
21
|
+
next unless config[:query] == Praxis::Mapper::Query::Sql
|
22
|
+
|
23
|
+
migration_path = @schema_root + repository_name.to_s
|
24
|
+
|
25
|
+
migration_path.children.each do |file|
|
26
|
+
table = file.basename.to_s[0..-4]
|
27
|
+
|
28
|
+
before = Sequel::Migration.descendants.clone
|
29
|
+
require file.expand_path if file.exist?
|
30
|
+
|
31
|
+
after = Sequel::Migration.descendants
|
32
|
+
|
33
|
+
migration = (after - before).first
|
34
|
+
|
35
|
+
@migrations[repository_name] ||= Array.new
|
36
|
+
@migrations[repository_name] << [table, migration]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def load!
|
44
|
+
@migrations.each do |repository_name, migrations|
|
45
|
+
connection = @connection_manager.checkout(repository_name)
|
46
|
+
|
47
|
+
migrations.each do |(table, migration)|
|
48
|
+
migration.apply(connection, :up)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
require 'sequel'
|
6
|
+
|
7
|
+
module Praxis
|
8
|
+
module Mapper
|
9
|
+
|
10
|
+
# Get the logger configured for Praxis::Mapper
|
11
|
+
#
|
12
|
+
# @example Basic usage
|
13
|
+
# Praxis::Mapper.logger.info 'Something interesting happened'
|
14
|
+
#
|
15
|
+
# @return [Logger] The currently configured logger or a STDOUT logger
|
16
|
+
#
|
17
|
+
def self.logger
|
18
|
+
@logger ||= begin
|
19
|
+
require 'logger'
|
20
|
+
Logger.new(STDOUT)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Set the logger configured for Praxis::Mapper
|
25
|
+
#
|
26
|
+
# @example Basic usage
|
27
|
+
# Praxis::Mapper.logger = Logger.new('log/development.log')
|
28
|
+
#
|
29
|
+
# @return [Logger] The logger object
|
30
|
+
#
|
31
|
+
def self.logger=(logger)
|
32
|
+
@logger = logger
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# Perform any final initialiation needed
|
37
|
+
def self.finalize!
|
38
|
+
Praxis::Mapper::Model.finalize!
|
39
|
+
Praxis::Mapper::Resource.finalize!
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'praxis-mapper/finalizable'
|
46
|
+
require 'praxis-mapper/logging'
|
47
|
+
|
48
|
+
require 'praxis-mapper/identity_map'
|
49
|
+
|
50
|
+
require 'praxis-mapper/model'
|
51
|
+
require 'praxis-mapper/query_statistics'
|
52
|
+
require 'praxis-mapper/connection_manager'
|
53
|
+
|
54
|
+
require 'praxis-mapper/resource'
|
55
|
+
|
56
|
+
require 'praxis-mapper/query/base'
|
57
|
+
require 'praxis-mapper/query/sql'
|
58
|
+
|
59
|
+
|
60
|
+
require 'praxis-mapper/config_hash'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'praxis-mapper/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "praxis-mapper"
|
8
|
+
spec.version = Praxis::Mapper::VERSION
|
9
|
+
spec.authors = ["Josep M. Blanquer","Dane Jensen"]
|
10
|
+
spec.date = "2014-08-18"
|
11
|
+
spec.summary = %q{A multi-datastore library designed for efficiency in loading large datasets.}
|
12
|
+
spec.email = ["blanquer@gmail.com","dane.jensen@gmail.com"]
|
13
|
+
|
14
|
+
spec.homepage = "https://github.com/rightscale/praxis-mapper"
|
15
|
+
spec.license = "MIT"
|
16
|
+
spec.required_ruby_version = ">=2.1"
|
17
|
+
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
|
22
|
+
spec.add_runtime_dependency(%q<randexp>, ["~> 0"])
|
23
|
+
spec.add_runtime_dependency(%q<sequel>, ["~> 4"])
|
24
|
+
spec.add_runtime_dependency(%q<activesupport>, ["~> 4"])
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
27
|
+
spec.add_development_dependency "rake", "~> 0"
|
28
|
+
|
29
|
+
spec.add_development_dependency(%q<redcarpet>, ["< 3.0"])
|
30
|
+
spec.add_development_dependency(%q<yard>, ["~> 0.8.7"])
|
31
|
+
spec.add_development_dependency(%q<guard>, ["~> 2"])
|
32
|
+
spec.add_development_dependency(%q<guard-rspec>, [">= 0"])
|
33
|
+
spec.add_development_dependency(%q<rspec>, ["< 2.99"])
|
34
|
+
spec.add_development_dependency(%q<pry>, ["~> 0"])
|
35
|
+
spec.add_development_dependency(%q<pry-byebug>, ["~> 1"])
|
36
|
+
spec.add_development_dependency(%q<pry-stack_explorer>, ["~> 0"])
|
37
|
+
spec.add_development_dependency(%q<fuubar>, ["~> 1"])
|
38
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
class DummyFactory
|
4
|
+
def initialize(opts)
|
5
|
+
@opts = opts
|
6
|
+
end
|
7
|
+
|
8
|
+
def opts
|
9
|
+
@opts
|
10
|
+
end
|
11
|
+
|
12
|
+
def checkout
|
13
|
+
end
|
14
|
+
|
15
|
+
def release(connection)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
describe Praxis::Mapper::ConnectionManager do
|
22
|
+
let(:mock_connection) { double("connection") }
|
23
|
+
|
24
|
+
let(:default_hash) { Hash.new }
|
25
|
+
let(:factory_opts) { {:foo => "bar"} }
|
26
|
+
let(:config) { {:dummy => {:connection_factory => "DummyFactory", :connection_opts => factory_opts}} }
|
27
|
+
|
28
|
+
let(:dummy_factory_mock) { double("dummy_factory")}
|
29
|
+
|
30
|
+
subject { Praxis::Mapper::ConnectionManager }
|
31
|
+
|
32
|
+
before do
|
33
|
+
Praxis::Mapper::ConnectionManager.setup(config)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'has a :dummy repository' do
|
37
|
+
repository = subject.repository(:dummy)
|
38
|
+
|
39
|
+
repository[:connection_factory].should be_kind_of(DummyFactory)
|
40
|
+
repository[:connection_factory].opts.should == factory_opts
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with repositories specified in a block for setup" do
|
44
|
+
let(:dummy_connection) { double("dummy connection")}
|
45
|
+
|
46
|
+
before do
|
47
|
+
opts = factory_opts
|
48
|
+
|
49
|
+
block = Proc.new { mock_connection }
|
50
|
+
Praxis::Mapper::ConnectionManager.setup do
|
51
|
+
repository :foo, &block
|
52
|
+
repository :bar, :connection_factory => "DummyFactory", :connection_opts => opts
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'supports proc-based repostories' do
|
57
|
+
subject.repository(:foo)[:connection_factory].should be_kind_of(Proc)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'supports config-based repositories' do
|
61
|
+
subject.repository(:bar)[:connection_factory].should be_kind_of(DummyFactory)
|
62
|
+
subject.repository(:bar)[:connection_factory].opts.should == factory_opts
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'getting connections' do
|
66
|
+
|
67
|
+
subject { Praxis::Mapper::ConnectionManager.new }
|
68
|
+
|
69
|
+
it 'gets connections from proc-based repositories' do
|
70
|
+
subject.checkout(:foo).should == mock_connection
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'gets connections from config-based repositories' do
|
74
|
+
DummyFactory.any_instance.should_receive(:checkout).and_return(dummy_connection)
|
75
|
+
subject.checkout(:bar).should == dummy_connection
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'releasing connections' do
|
81
|
+
subject { Praxis::Mapper::ConnectionManager.new }
|
82
|
+
|
83
|
+
it 'releases connections from config-based repositories' do
|
84
|
+
|
85
|
+
DummyFactory.any_instance.should_receive(:checkout).exactly(2).times.and_return(dummy_connection)
|
86
|
+
DummyFactory.any_instance.should_receive(:release).with(dummy_connection).and_return(true)
|
87
|
+
|
88
|
+
subject.checkout(:bar)
|
89
|
+
subject.checkout(:bar)
|
90
|
+
|
91
|
+
subject.release(:bar)
|
92
|
+
|
93
|
+
subject.checkout(:bar)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'releases connections from proc-based repositories' do
|
97
|
+
subject.checkout(:foo)
|
98
|
+
subject.release(:foo)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'releases all connections' do
|
102
|
+
DummyFactory.any_instance.should_receive(:checkout).exactly(1).times.and_return(dummy_connection)
|
103
|
+
DummyFactory.any_instance.should_receive(:release).with(dummy_connection).and_return(true)
|
104
|
+
|
105
|
+
subject.checkout(:bar)
|
106
|
+
|
107
|
+
subject.should_not_receive(:release_one).with(:foo).and_call_original
|
108
|
+
subject.should_receive(:release_one).with(:bar).and_call_original
|
109
|
+
|
110
|
+
subject.release
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|