praxis-mapper 3.1.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.
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