praxis-mapper 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +26 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +4 -0
  5. data/CHANGELOG.md +83 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +102 -0
  8. data/Guardfile +11 -0
  9. data/LICENSE +22 -0
  10. data/README.md +19 -0
  11. data/Rakefile +14 -0
  12. data/lib/praxis-mapper/config_hash.rb +40 -0
  13. data/lib/praxis-mapper/connection_manager.rb +102 -0
  14. data/lib/praxis-mapper/finalizable.rb +38 -0
  15. data/lib/praxis-mapper/identity_map.rb +532 -0
  16. data/lib/praxis-mapper/logging.rb +22 -0
  17. data/lib/praxis-mapper/model.rb +430 -0
  18. data/lib/praxis-mapper/query/base.rb +213 -0
  19. data/lib/praxis-mapper/query/sql.rb +183 -0
  20. data/lib/praxis-mapper/query_statistics.rb +46 -0
  21. data/lib/praxis-mapper/resource.rb +226 -0
  22. data/lib/praxis-mapper/support/factory_girl.rb +104 -0
  23. data/lib/praxis-mapper/support/memory_query.rb +34 -0
  24. data/lib/praxis-mapper/support/memory_repository.rb +44 -0
  25. data/lib/praxis-mapper/support/schema_dumper.rb +66 -0
  26. data/lib/praxis-mapper/support/schema_loader.rb +56 -0
  27. data/lib/praxis-mapper/support.rb +2 -0
  28. data/lib/praxis-mapper/version.rb +5 -0
  29. data/lib/praxis-mapper.rb +60 -0
  30. data/praxis-mapper.gemspec +38 -0
  31. data/spec/praxis-mapper/connection_manager_spec.rb +117 -0
  32. data/spec/praxis-mapper/identity_map_spec.rb +905 -0
  33. data/spec/praxis-mapper/logging_spec.rb +9 -0
  34. data/spec/praxis-mapper/memory_repository_spec.rb +56 -0
  35. data/spec/praxis-mapper/model_spec.rb +389 -0
  36. data/spec/praxis-mapper/query/base_spec.rb +317 -0
  37. data/spec/praxis-mapper/query/sql_spec.rb +184 -0
  38. data/spec/praxis-mapper/resource_spec.rb +154 -0
  39. data/spec/praxis_mapper_spec.rb +21 -0
  40. data/spec/spec_fixtures.rb +12 -0
  41. data/spec/spec_helper.rb +63 -0
  42. data/spec/support/spec_models.rb +215 -0
  43. data/spec/support/spec_resources.rb +39 -0
  44. 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,2 @@
1
+ require_relative 'support/memory_query'
2
+ require_relative 'support/memory_repository'
@@ -0,0 +1,5 @@
1
+ module Praxis
2
+ module Mapper
3
+ VERSION = "3.1.1"
4
+ end
5
+ 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