rom-mapper 0.1.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 (52) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +3 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +21 -0
  6. data/Gemfile +19 -0
  7. data/Gemfile.devtools +55 -0
  8. data/Guardfile +19 -0
  9. data/LICENSE +20 -0
  10. data/README.md +21 -0
  11. data/Rakefile +7 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/mutant.yml +3 -0
  16. data/config/reek.yml +105 -0
  17. data/config/rubocop.yml +45 -0
  18. data/lib/rom-mapper.rb +17 -0
  19. data/lib/rom/mapper.rb +135 -0
  20. data/lib/rom/mapper/attribute.rb +26 -0
  21. data/lib/rom/mapper/dumper.rb +27 -0
  22. data/lib/rom/mapper/header.rb +78 -0
  23. data/lib/rom/mapper/loader.rb +22 -0
  24. data/lib/rom/mapper/loader/allocator.rb +32 -0
  25. data/lib/rom/mapper/loader/attribute_writer.rb +23 -0
  26. data/lib/rom/mapper/loader/object_builder.rb +28 -0
  27. data/lib/rom/version.rb +11 -0
  28. data/rom-mapper.gemspec +23 -0
  29. data/spec/shared/unit/loader_call.rb +13 -0
  30. data/spec/shared/unit/loader_identity.rb +13 -0
  31. data/spec/shared/unit/mapper_context.rb +13 -0
  32. data/spec/spec_helper.rb +48 -0
  33. data/spec/unit/rom/mapper/call_spec.rb +32 -0
  34. data/spec/unit/rom/mapper/class_methods/build_spec.rb +64 -0
  35. data/spec/unit/rom/mapper/dump_spec.rb +15 -0
  36. data/spec/unit/rom/mapper/dumper/call_spec.rb +29 -0
  37. data/spec/unit/rom/mapper/dumper/identity_spec.rb +28 -0
  38. data/spec/unit/rom/mapper/header/each_spec.rb +28 -0
  39. data/spec/unit/rom/mapper/header/element_reader_spec.rb +25 -0
  40. data/spec/unit/rom/mapper/header/keys_spec.rb +32 -0
  41. data/spec/unit/rom/mapper/identity_from_tuple_spec.rb +15 -0
  42. data/spec/unit/rom/mapper/identity_spec.rb +15 -0
  43. data/spec/unit/rom/mapper/load_spec.rb +15 -0
  44. data/spec/unit/rom/mapper/loader/allocator/call_spec.rb +7 -0
  45. data/spec/unit/rom/mapper/loader/allocator/identity_spec.rb +7 -0
  46. data/spec/unit/rom/mapper/loader/attribute_writer/call_spec.rb +7 -0
  47. data/spec/unit/rom/mapper/loader/attribute_writer/identity_spec.rb +7 -0
  48. data/spec/unit/rom/mapper/loader/object_builder/call_spec.rb +7 -0
  49. data/spec/unit/rom/mapper/loader/object_builder/identity_spec.rb +7 -0
  50. data/spec/unit/rom/mapper/model_spec.rb +11 -0
  51. data/spec/unit/rom/mapper/new_object_spec.rb +14 -0
  52. metadata +177 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ log
2
+ *.rbx
3
+ *.rbc
4
+ Gemfile.lock
5
+ tmp/
6
+ doc/
7
+ coverage/
8
+ measurements/
9
+ graphviz/
10
+ .yardoc/
11
+ .bundle/
12
+ *.png
13
+ Vagrantfile
14
+ .vagrant
15
+
16
+ # spiking area
17
+ scratchpad.rb
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --profile
3
+ --order random
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ rom
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3
data/.travis.yml ADDED
@@ -0,0 +1,21 @@
1
+ language: ruby
2
+ bundler_args: --without yard guard benchmarks
3
+ script: "bundle exec rake ci"
4
+ rvm:
5
+ - 1.9.3
6
+ - 2.0.0
7
+ - ruby-head
8
+ - rbx-19mode
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: jruby-19mode
12
+ - rvm: ruby-head
13
+ notifications:
14
+ irc:
15
+ channels:
16
+ - "irc.freenode.org#rom-rb"
17
+ on_success: never
18
+ on_failure: change
19
+ email:
20
+ on_success: never
21
+ on_failure: change
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'rom-mapper', path: '.'
8
+
9
+ group :test do
10
+ gem 'bogus', '~> 0.1'
11
+ gem 'axiom', '~> 0.1'
12
+ end
13
+
14
+ group :development do
15
+ gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
16
+ end
17
+
18
+ # Added by devtools
19
+ eval_gemfile 'Gemfile.devtools'
data/Gemfile.devtools ADDED
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ group :development do
4
+ gem 'rake', '~> 10.1.0'
5
+ gem 'rspec', '~> 2.14.1'
6
+ gem 'yard', '~> 0.8.7'
7
+ end
8
+
9
+ group :yard do
10
+ gem 'kramdown', '~> 1.1.0'
11
+ end
12
+
13
+ group :guard do
14
+ gem 'guard', '~> 1.8.1'
15
+ gem 'guard-bundler', '~> 1.0.0'
16
+ gem 'guard-rspec', '~> 3.0.2'
17
+ gem 'guard-rubocop', '~> 0.2.0'
18
+ gem 'guard-mutant', '~> 0.0.1'
19
+
20
+ # file system change event handling
21
+ gem 'listen', '~> 1.2.2'
22
+ gem 'rb-fchange', '~> 0.0.6', require: false
23
+ gem 'rb-fsevent', '~> 0.9.3', require: false
24
+ gem 'rb-inotify', '~> 0.9.0', require: false
25
+
26
+ # notification handling
27
+ gem 'libnotify', '~> 0.8.0', require: false
28
+ gem 'rb-notifu', '~> 0.0.4', require: false
29
+ gem 'terminal-notifier-guard', '~> 1.5.3', require: false
30
+ end
31
+
32
+ group :metrics do
33
+ gem 'coveralls', '~> 0.6.7'
34
+ gem 'flay', '~> 2.4.0'
35
+ gem 'flog', '~> 4.1.1'
36
+ gem 'reek', '~> 1.3.2'
37
+ gem 'rubocop', '~> 0.11.0'
38
+ gem 'simplecov', '~> 0.7.1'
39
+ gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
40
+
41
+ platforms :ruby_19, :ruby_20 do
42
+ gem 'mutant', git: 'https://github.com/mbj/mutant.git'
43
+ gem 'yard-spellcheck', '~> 0.1.5'
44
+ end
45
+ end
46
+
47
+ group :benchmarks do
48
+ gem 'rbench', '~> 0.2.3'
49
+ end
50
+
51
+ platform :jruby do
52
+ group :jruby do
53
+ gem 'jruby-openssl', '~> 0.8.5'
54
+ end
55
+ end
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ guard :rspec do
2
+ #run all specs if configuration is modified
3
+ watch('Guardfile') { 'spec' }
4
+ watch('Gemfile.lock') { 'spec' }
5
+ watch('spec/spec_helper.rb') { 'spec' }
6
+
7
+ # run all specs if supporting files files are modified
8
+ watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec' }
9
+
10
+ # run unit specs if associated lib code is modified
11
+ watch(%r{\Alib/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}"] }
12
+ watch(%r{\Alib/(.+)/support/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}/#{m[2]}"] }
13
+ watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' }
14
+
15
+ # run a spec if it is modified
16
+ watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
17
+
18
+ notification :tmux, :display_message => true
19
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Ruby Object Mapper Team
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # rom-mapper
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rom-mapper.png)][gem]
4
+ [![Build Status](https://travis-ci.org/rom-rb/rom-mapper.png?branch=master)][travis]
5
+ [![Dependency Status](https://gemnasium.com/rom-rb/rom-mapper.png)][gemnasium]
6
+ [![Code Climate](https://codeclimate.com/github/rom-rb/rom-mapper.png)][codeclimate]
7
+ [![Coverage Status](https://coveralls.io/repos/rom-rb/rom-mapper/badge.png?branch=master)][coveralls]
8
+
9
+ [gem]: https://rubygems.org/gems/rom-mapper
10
+ [travis]: https://travis-ci.org/rom-rb/rom-mapper
11
+ [gemnasium]: https://gemnasium.com/rom-rb/rom-mapper
12
+ [codeclimate]: https://codeclimate.com/github/rom-rb/rom-mapper
13
+ [coveralls]: https://coveralls.io/r/rom-rb/rom-mapper
14
+
15
+ Mappers for [Ruby Object Mapper](http://rom-rb.org).
16
+
17
+ See ROM's [README](https://github.com/rom-rb/rom) for more information.
18
+
19
+ ## License
20
+
21
+ See LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'devtools'
4
+
5
+ Devtools.init_rake_tasks
6
+
7
+ require 'rspec/core/rake_task'
@@ -0,0 +1,2 @@
1
+ ---
2
+ unit_test_timeout: 0.1
data/config/flay.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ threshold: 7
3
+ total_score: 55
data/config/flog.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 13.7
data/config/mutant.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ name: rom-mapper
3
+ namespace: ROM::Mapper
data/config/reek.yml ADDED
@@ -0,0 +1,105 @@
1
+ ---
2
+ Attribute:
3
+ enabled: true
4
+ exclude: []
5
+ BooleanParameter:
6
+ enabled: true
7
+ exclude: []
8
+ ClassVariable:
9
+ enabled: true
10
+ exclude: []
11
+ ControlParameter:
12
+ enabled: true
13
+ exclude: []
14
+ DataClump:
15
+ enabled: true
16
+ exclude: []
17
+ max_copies: 2
18
+ min_clump_size: 2
19
+ DuplicateMethodCall:
20
+ enabled: false
21
+ FeatureEnvy:
22
+ enabled: true
23
+ exclude:
24
+ - ROM::Mapper::Loader::Allocator#call
25
+ - ROM::Mapper::Loader::AttributeWriter#call
26
+ - ROM::Mapper::Loader::ObjectBuilder#attributes
27
+ - ROM::Mapper::Header#mapping
28
+ IrresponsibleModule:
29
+ enabled: true
30
+ exclude: []
31
+ LongParameterList:
32
+ enabled: true
33
+ exclude:
34
+ - ROM::Mapper#self.build
35
+ max_params: 2
36
+ LongYieldList:
37
+ enabled: true
38
+ exclude: []
39
+ max_params: 2
40
+ NestedIterators:
41
+ enabled: true
42
+ max_allowed_nesting: 1
43
+ ignore_iterators: []
44
+ exclude:
45
+ - ROM::Mapper::Header#keys
46
+ NilCheck:
47
+ enabled: true
48
+ exclude: []
49
+ RepeatedConditional:
50
+ enabled: true
51
+ exclude: []
52
+ max_ifs: 1
53
+ TooManyInstanceVariables:
54
+ enabled: true
55
+ exclude: []
56
+ max_instance_variables: 3
57
+ TooManyMethods:
58
+ enabled: true
59
+ exclude: []
60
+ max_methods: 10
61
+ TooManyStatements:
62
+ enabled: true
63
+ exclude:
64
+ - each
65
+ - ROM::Mapper#self.build
66
+ - ROM::Mapper::Header#self.build
67
+ max_statements: 4
68
+ UncommunicativeMethodName:
69
+ enabled: true
70
+ exclude: []
71
+ reject:
72
+ - !ruby/regexp /^[a-z]$/
73
+ - !ruby/regexp /[0-9]$/
74
+ - !ruby/regexp /[A-Z]/
75
+ accept: []
76
+ UncommunicativeModuleName:
77
+ enabled: true
78
+ exclude: []
79
+ reject:
80
+ - !ruby/regexp /^.$/
81
+ - !ruby/regexp /[0-9]$/
82
+ accept: []
83
+ UncommunicativeParameterName:
84
+ enabled: true
85
+ exclude: []
86
+ reject:
87
+ - !ruby/regexp /^.$/
88
+ - !ruby/regexp /[0-9]$/
89
+ - !ruby/regexp /[A-Z]/
90
+ accept: []
91
+ UncommunicativeVariableName:
92
+ enabled: true
93
+ exclude: []
94
+ reject:
95
+ - !ruby/regexp /^.$/
96
+ - !ruby/regexp /[0-9]$/
97
+ - !ruby/regexp /[A-Z]/
98
+ accept: []
99
+ UnusedParameters:
100
+ enabled: true
101
+ exclude: []
102
+ UtilityFunction:
103
+ enabled: true
104
+ exclude: []
105
+ max_helper_calls: 0
@@ -0,0 +1,45 @@
1
+ AllCops:
2
+ Includes:
3
+ - '**/*.rake'
4
+ - 'Gemfile'
5
+ - 'Gemfile.devtools'
6
+ Excludes:
7
+ - '**/vendor/**'
8
+
9
+ # Avoid parameter lists longer than five parameters.
10
+ ParameterLists:
11
+ Max: 3
12
+ CountKeywordArgs: true
13
+
14
+ # Avoid more than `Max` levels of nesting.
15
+ BlockNesting:
16
+ Max: 3
17
+
18
+ # Align with the style guide.
19
+ CollectionMethods:
20
+ PreferredMethods:
21
+ collect: 'map'
22
+ inject: 'reduce'
23
+ find: 'detect'
24
+ find_all: 'select'
25
+
26
+ # Do not force public/protected/private keyword to be indented at the same
27
+ # level as the def keyword. My personal preference is to outdent these keywords
28
+ # because I think when scanning code it makes it easier to identify the
29
+ # sections of code and visually separate them. When the keyword is at the same
30
+ # level I think it sort of blends in with the def keywords and makes it harder
31
+ # to scan the code and see where the sections are.
32
+ AccessControl:
33
+ Enabled: false
34
+
35
+ LineLength:
36
+ Max: 108
37
+
38
+ Blocks:
39
+ Enabled: false
40
+
41
+ Documentation:
42
+ Enabled: false
43
+
44
+ EmptyLineBetweenDefs:
45
+ Enabled: false # TODO: re-enable once SpecHelper.mock_model case is properly handled
data/lib/rom-mapper.rb ADDED
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'concord'
4
+ require 'adamantium'
5
+ require 'equalizer'
6
+ require 'abstract_type'
7
+
8
+ require 'rom/mapper/attribute'
9
+ require 'rom/mapper/header'
10
+
11
+ require 'rom/mapper/loader'
12
+ require 'rom/mapper/loader/allocator'
13
+ require 'rom/mapper/loader/attribute_writer'
14
+ require 'rom/mapper/loader/object_builder'
15
+
16
+ require 'rom/mapper/dumper'
17
+ require 'rom/mapper'
data/lib/rom/mapper.rb ADDED
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+
3
+ module ROM
4
+
5
+ # Mappers load tuples into objects and dump objects back into tuples
6
+ #
7
+ class Mapper
8
+ include Concord::Public.new(:header, :loader, :dumper)
9
+
10
+ LOADERS = {
11
+ allocator: Loader::Allocator,
12
+ object_builder: Loader::ObjectBuilder,
13
+ attribute_writer: Loader::AttributeWriter
14
+ }
15
+
16
+ DUMPERS = {
17
+ default: Dumper
18
+ }
19
+
20
+ DEFAULT_LOADER = :allocator
21
+ DEFAULT_DUMPER = :default
22
+
23
+ # Build a mapper
24
+ #
25
+ # @example
26
+ #
27
+ # header = Mapper::Header.build([[:user_name, String]], map: { user_name: :name })
28
+ #
29
+ # mapper = Mapper.build(header, User)
30
+ # mapper = Mapper.build(header, User, loader_class: Loader::ObjectBuilder)
31
+ #
32
+ # @param [Header]
33
+ # @param [Class]
34
+ # @param [Hash]
35
+ #
36
+ # @return [Mapper]
37
+ #
38
+ # @api public
39
+ def self.build(header, model, options = {})
40
+ loader_class = LOADERS[options.fetch(:loader, DEFAULT_LOADER)]
41
+ dumper_class = DUMPERS[options.fetch(:dumper, DEFAULT_DUMPER)]
42
+
43
+ header = Header.build(header, options)
44
+ loader = loader_class.new(header, model)
45
+ dumper = dumper_class.new(header)
46
+
47
+ new(header, loader, dumper)
48
+ end
49
+
50
+ # Project and rename given relation
51
+ #
52
+ # @example
53
+ #
54
+ # mapper.call(relation)
55
+ #
56
+ # @param [Axiom::Relation]
57
+ #
58
+ # @return [Axiom::Relation]
59
+ #
60
+ # @api public
61
+ def call(relation)
62
+ mapping = header.mapping
63
+ attributes = mapping.keys
64
+
65
+ relation.project(attributes).rename(mapping)
66
+ end
67
+
68
+ # Retrieve identity from the given object
69
+ #
70
+ # @example
71
+ #
72
+ # mapper.identity(user) # => [1]
73
+ #
74
+ # @param [Object]
75
+ #
76
+ # @return [Array]
77
+ #
78
+ # @api public
79
+ def identity(object)
80
+ dumper.identity(object)
81
+ end
82
+
83
+ # Return identity from the given tuple
84
+ #
85
+ # @example
86
+ #
87
+ # mapper.identity_from_tuple({id: 1}) # => [1]
88
+ #
89
+ # @param [Axiom::Tuple,Hash]
90
+ #
91
+ # @return [Array]
92
+ #
93
+ # @api public
94
+ def identity_from_tuple(tuple)
95
+ loader.identity(tuple)
96
+ end
97
+
98
+ # Build a new model instance
99
+ #
100
+ # @example
101
+ #
102
+ # mapper = Mapper.build(header, User)
103
+ # mapper.new_object(id: 1, name: 'Jane') # => #<User @id=1 @name="Jane">
104
+ #
105
+ # @api public
106
+ def new_object(*args, &block)
107
+ model.new(*args, &block)
108
+ end
109
+
110
+ # Return model used by this mapper
111
+ #
112
+ # @return [Class]
113
+ #
114
+ # @api public
115
+ def model
116
+ loader.model
117
+ end
118
+
119
+ # Load an object instance from the tuple
120
+ #
121
+ # @api private
122
+ def load(tuple)
123
+ loader.call(tuple)
124
+ end
125
+
126
+ # Dump an object into a tuple
127
+ #
128
+ # @api private
129
+ def dump(object)
130
+ dumper.call(object)
131
+ end
132
+
133
+ end # Mapper
134
+
135
+ end # ROM