rom-mapper 0.1.0

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