rom 0.2.0 → 0.3.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 (175) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -3
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +13 -14
  5. data/{Changelog.md → CHANGELOG.md} +12 -3
  6. data/Gemfile +14 -10
  7. data/Gemfile.devtools +16 -16
  8. data/Guardfile +2 -5
  9. data/README.md +68 -56
  10. data/Rakefile +3 -3
  11. data/config/flay.yml +2 -2
  12. data/config/mutant.yml +2 -4
  13. data/config/rubocop.yml +30 -0
  14. data/lib/rom.rb +47 -9
  15. data/lib/rom/adapter.rb +52 -0
  16. data/lib/rom/adapter/memory.rb +70 -0
  17. data/lib/rom/boot.rb +158 -0
  18. data/lib/rom/boot/base_relation_dsl.rb +43 -0
  19. data/lib/rom/boot/dsl.rb +30 -0
  20. data/lib/rom/boot/mapper_dsl.rb +23 -0
  21. data/lib/rom/boot/relation_dsl.rb +23 -0
  22. data/lib/rom/boot/schema_dsl.rb +27 -0
  23. data/lib/rom/env.rb +48 -0
  24. data/lib/rom/header.rb +123 -0
  25. data/lib/rom/mapper.rb +38 -153
  26. data/lib/rom/mapper_builder.rb +85 -0
  27. data/lib/rom/model_builder.rb +58 -0
  28. data/lib/rom/ra.rb +196 -0
  29. data/lib/rom/ra/operation/group.rb +49 -0
  30. data/lib/rom/ra/operation/join.rb +41 -0
  31. data/lib/rom/ra/operation/wrap.rb +45 -0
  32. data/lib/rom/reader.rb +62 -0
  33. data/lib/rom/reader_builder.rb +28 -0
  34. data/lib/rom/relation.rb +41 -350
  35. data/lib/rom/relation_builder.rb +48 -0
  36. data/lib/rom/repository.rb +28 -53
  37. data/lib/rom/support/registry.rb +34 -0
  38. data/lib/rom/version.rb +3 -0
  39. data/rom.gemspec +12 -10
  40. data/spec/integration/adapters/extending_relations_spec.rb +43 -0
  41. data/spec/integration/mappers/definition_dsl_spec.rb +82 -0
  42. data/spec/integration/mappers/prefixing_attributes_spec.rb +42 -0
  43. data/spec/integration/mappers/renaming_attributes_spec.rb +138 -0
  44. data/spec/integration/ra/group_spec.rb +47 -0
  45. data/spec/integration/ra/join_spec.rb +24 -0
  46. data/spec/integration/ra/wrap_spec.rb +37 -0
  47. data/spec/integration/relations/reading_spec.rb +116 -0
  48. data/spec/integration/relations/registry_dsl_spec.rb +44 -0
  49. data/spec/integration/schema_spec.rb +29 -0
  50. data/spec/integration/setup_spec.rb +18 -0
  51. data/spec/shared/users_and_tasks.rb +34 -0
  52. data/spec/spec_helper.rb +14 -36
  53. data/spec/unit/rom/adapter_spec.rb +59 -0
  54. data/spec/unit/rom/header_spec.rb +58 -0
  55. data/spec/unit/rom/mapper_spec.rb +27 -0
  56. data/spec/unit/rom/ra/operation/group_spec.rb +55 -0
  57. data/spec/unit/rom/ra/operation/wrap_spec.rb +29 -0
  58. data/spec/unit/rom/relation_spec.rb +34 -0
  59. metadata +122 -190
  60. data/lib/rom/constants.rb +0 -16
  61. data/lib/rom/environment.rb +0 -105
  62. data/lib/rom/environment/builder.rb +0 -71
  63. data/lib/rom/mapper/attribute.rb +0 -108
  64. data/lib/rom/mapper/builder.rb +0 -58
  65. data/lib/rom/mapper/builder/definition.rb +0 -162
  66. data/lib/rom/mapper/header.rb +0 -103
  67. data/lib/rom/mapper/loader_builder.rb +0 -26
  68. data/lib/rom/schema.rb +0 -21
  69. data/lib/rom/schema/builder.rb +0 -59
  70. data/lib/rom/schema/definition.rb +0 -84
  71. data/lib/rom/schema/definition/relation.rb +0 -80
  72. data/lib/rom/schema/definition/relation/base.rb +0 -27
  73. data/lib/rom/session.rb +0 -111
  74. data/lib/rom/session/environment.rb +0 -67
  75. data/lib/rom/session/identity_map.rb +0 -43
  76. data/lib/rom/session/mapper.rb +0 -62
  77. data/lib/rom/session/relation.rb +0 -140
  78. data/lib/rom/session/state.rb +0 -59
  79. data/lib/rom/session/state/created.rb +0 -22
  80. data/lib/rom/session/state/deleted.rb +0 -25
  81. data/lib/rom/session/state/persisted.rb +0 -34
  82. data/lib/rom/session/state/transient.rb +0 -20
  83. data/lib/rom/session/state/updated.rb +0 -29
  84. data/lib/rom/session/tracker.rb +0 -62
  85. data/lib/rom/support/axiom/adapter.rb +0 -111
  86. data/lib/rom/support/axiom/adapter/data_objects.rb +0 -38
  87. data/lib/rom/support/axiom/adapter/memory.rb +0 -25
  88. data/lib/rom/support/axiom/adapter/postgres.rb +0 -19
  89. data/lib/rom/support/axiom/adapter/sqlite3.rb +0 -20
  90. data/lib/version.rb +0 -3
  91. data/spec/integration/environment_setup_spec.rb +0 -24
  92. data/spec/integration/grouped_mappers_spec.rb +0 -87
  93. data/spec/integration/join_and_group_spec.rb +0 -76
  94. data/spec/integration/join_and_wrap_spec.rb +0 -68
  95. data/spec/integration/mapping_embedded_relations_spec.rb +0 -73
  96. data/spec/integration/mapping_relations_spec.rb +0 -120
  97. data/spec/integration/schema_definition_spec.rb +0 -152
  98. data/spec/integration/session_spec.rb +0 -87
  99. data/spec/integration/wrapped_mappers_spec.rb +0 -73
  100. data/spec/shared/unit/environment_context.rb +0 -6
  101. data/spec/shared/unit/loader.rb +0 -11
  102. data/spec/shared/unit/loader_identity.rb +0 -13
  103. data/spec/shared/unit/mapper_context.rb +0 -11
  104. data/spec/shared/unit/relation_context.rb +0 -82
  105. data/spec/shared/unit/session_environment_context.rb +0 -11
  106. data/spec/shared/unit/session_relation_context.rb +0 -18
  107. data/spec/support/helper.rb +0 -34
  108. data/spec/support/ice_nine_config.rb +0 -10
  109. data/spec/support/test_mapper.rb +0 -110
  110. data/spec/unit/rom/environment/builder/mapping_spec.rb +0 -24
  111. data/spec/unit/rom/environment/builder/schema_spec.rb +0 -33
  112. data/spec/unit/rom/environment/class_methods/setup_spec.rb +0 -18
  113. data/spec/unit/rom/environment/repository_spec.rb +0 -21
  114. data/spec/unit/rom/mapper/attribute/embedded_collection/to_ast_spec.rb +0 -18
  115. data/spec/unit/rom/mapper/attribute/embedded_value/to_ast_spec.rb +0 -16
  116. data/spec/unit/rom/mapper/attribute/rename_spec.rb +0 -9
  117. data/spec/unit/rom/mapper/attribute/to_ast_spec.rb +0 -9
  118. data/spec/unit/rom/mapper/builder/class_methods/call_spec.rb +0 -61
  119. data/spec/unit/rom/mapper/class_methods/build_spec.rb +0 -55
  120. data/spec/unit/rom/mapper/dump_spec.rb +0 -11
  121. data/spec/unit/rom/mapper/group_spec.rb +0 -35
  122. data/spec/unit/rom/mapper/header/each_spec.rb +0 -26
  123. data/spec/unit/rom/mapper/header/element_reader_spec.rb +0 -21
  124. data/spec/unit/rom/mapper/header/group_spec.rb +0 -18
  125. data/spec/unit/rom/mapper/header/join_spec.rb +0 -14
  126. data/spec/unit/rom/mapper/header/keys_spec.rb +0 -29
  127. data/spec/unit/rom/mapper/header/project_spec.rb +0 -13
  128. data/spec/unit/rom/mapper/header/rename_spec.rb +0 -11
  129. data/spec/unit/rom/mapper/header/to_ast_spec.rb +0 -11
  130. data/spec/unit/rom/mapper/header/wrap_spec.rb +0 -18
  131. data/spec/unit/rom/mapper/identity_from_tuple_spec.rb +0 -11
  132. data/spec/unit/rom/mapper/identity_spec.rb +0 -11
  133. data/spec/unit/rom/mapper/join_spec.rb +0 -15
  134. data/spec/unit/rom/mapper/load_spec.rb +0 -11
  135. data/spec/unit/rom/mapper/new_object_spec.rb +0 -14
  136. data/spec/unit/rom/mapper/project_spec.rb +0 -11
  137. data/spec/unit/rom/mapper/rename_spec.rb +0 -16
  138. data/spec/unit/rom/mapper/wrap_spec.rb +0 -35
  139. data/spec/unit/rom/relation/delete_spec.rb +0 -15
  140. data/spec/unit/rom/relation/drop_spec.rb +0 -11
  141. data/spec/unit/rom/relation/each_spec.rb +0 -23
  142. data/spec/unit/rom/relation/first_spec.rb +0 -19
  143. data/spec/unit/rom/relation/group_spec.rb +0 -29
  144. data/spec/unit/rom/relation/inject_mapper_spec.rb +0 -17
  145. data/spec/unit/rom/relation/insert_spec.rb +0 -13
  146. data/spec/unit/rom/relation/last_spec.rb +0 -19
  147. data/spec/unit/rom/relation/one_spec.rb +0 -49
  148. data/spec/unit/rom/relation/rename_spec.rb +0 -21
  149. data/spec/unit/rom/relation/replace_spec.rb +0 -13
  150. data/spec/unit/rom/relation/restrict_spec.rb +0 -25
  151. data/spec/unit/rom/relation/sort_by_spec.rb +0 -25
  152. data/spec/unit/rom/relation/take_spec.rb +0 -11
  153. data/spec/unit/rom/relation/to_a_spec.rb +0 -20
  154. data/spec/unit/rom/relation/update_spec.rb +0 -25
  155. data/spec/unit/rom/relation/wrap_spec.rb +0 -29
  156. data/spec/unit/rom/repository/class_methods/build_spec.rb +0 -27
  157. data/spec/unit/rom/repository/element_reader_spec.rb +0 -21
  158. data/spec/unit/rom/repository/element_writer_spec.rb +0 -18
  159. data/spec/unit/rom/schema/builder/class_methods/build_spec.rb +0 -103
  160. data/spec/unit/rom/schema/element_reader_spec.rb +0 -15
  161. data/spec/unit/rom/session/class_methods/start_spec.rb +0 -23
  162. data/spec/unit/rom/session/clean_predicate_spec.rb +0 -21
  163. data/spec/unit/rom/session/environment/element_reader_spec.rb +0 -13
  164. data/spec/unit/rom/session/flush_spec.rb +0 -58
  165. data/spec/unit/rom/session/mapper/load_spec.rb +0 -47
  166. data/spec/unit/rom/session/relation/delete_spec.rb +0 -28
  167. data/spec/unit/rom/session/relation/dirty_predicate_spec.rb +0 -35
  168. data/spec/unit/rom/session/relation/identity_spec.rb +0 -11
  169. data/spec/unit/rom/session/relation/new_spec.rb +0 -50
  170. data/spec/unit/rom/session/relation/save_spec.rb +0 -50
  171. data/spec/unit/rom/session/relation/state_spec.rb +0 -23
  172. data/spec/unit/rom/session/relation/track_spec.rb +0 -23
  173. data/spec/unit/rom/session/relation/tracking_predicate_spec.rb +0 -23
  174. data/spec/unit/rom/session/relation/update_attributes_spec.rb +0 -45
  175. data/spec/unit/rom/session/state_spec.rb +0 -79
@@ -1,71 +1,46 @@
1
- # encoding: utf-8
2
-
3
- require 'rom/support/axiom/adapter'
4
-
5
1
  module ROM
6
2
 
7
- # A repository with a given +name+ and +adapter+
3
+ # Repository exposes native database connection and schema when it's
4
+ # supported by the adapter
8
5
  #
9
- # @api private
6
+ # @api public
10
7
  class Repository
11
- include Concord.new(:name, :adapter, :relations)
8
+ include Concord::Public.new(:adapter)
12
9
 
13
- # Build a repository with a given +name+ and +uri+
14
- #
15
- # @param [Symbol] name
16
- # the repository's name
10
+ # Return the dataset identified by name
17
11
  #
18
- # @param [Addressable::URI] uri
19
- # the uri for initializing the adapter
12
+ # @param [String,Symbol] name
20
13
  #
21
- # @return [Repository]
22
- #
23
- # @api private
24
- def self.build(name, uri, relations = {})
25
- new(name, Axiom::Adapter.build(uri), relations)
14
+ # @api public
15
+ def [](name)
16
+ adapter[name]
26
17
  end
27
18
 
28
- # Return the relation identified by +name+
29
- #
30
- # @example
31
- #
32
- # repo = Repository.coerce(:test, 'in_memory://test')
33
- # repo.register(:foo, [[:id, String], [:foo, String]])
34
- # repo[:foo]
35
- #
36
- # # => <Axiom::Relation header=Axiom::Header ...>
37
- #
38
- # @param [Symbol] name
39
- # the name of the relation
40
- #
41
- # @return [Axiom::Relation]
42
- #
43
- # @raise [KeyError]
19
+ # Return the database connection provided by the adapter
44
20
  #
45
21
  # @api public
46
- def [](name)
47
- relations.fetch(name)
22
+ def connection
23
+ adapter.connection
48
24
  end
49
25
 
50
- # Register a relation with this repository
51
- #
52
- # @param [Axiom::Relation::Base] relation
26
+ # Return the schema provided by the adapter
53
27
  #
54
- # @return [Object] relation gateway
55
- #
56
- # @api public
57
- def []=(name, relation)
58
- relation =
59
- if adapter.respond_to?(:gateway)
60
- adapter.gateway(relation)
61
- else
62
- adapter[name] = relation
63
- adapter[name]
64
- end
28
+ # @api private
29
+ def schema
30
+ adapter.schema
31
+ end
65
32
 
66
- relations[name] = relation
33
+ # @api private
34
+ def respond_to_missing?(name, include_private = false)
35
+ adapter[name]
67
36
  end
68
37
 
69
- end # Repository
38
+ private
39
+
40
+ # @api private
41
+ def method_missing(name)
42
+ adapter[name]
43
+ end
44
+ end
70
45
 
71
- end # ROM
46
+ end
@@ -0,0 +1,34 @@
1
+ module ROM
2
+
3
+ # @api private
4
+ class Registry
5
+ include Enumerable
6
+
7
+ attr_reader :elements
8
+
9
+ def initialize(elements = {})
10
+ @elements = elements
11
+ end
12
+
13
+ def each(&block)
14
+ return to_enum unless block
15
+ elements.each(&block)
16
+ end
17
+
18
+ def [](name)
19
+ elements[name]
20
+ end
21
+
22
+ def respond_to_missing?(name, include_private = false)
23
+ key?(name) || super
24
+ end
25
+
26
+ private
27
+
28
+ def method_missing(name, *args)
29
+ self[name]
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,3 @@
1
+ module ROM
2
+ VERSION = '0.3.0'.freeze
3
+ end
data/rom.gemspec CHANGED
@@ -1,13 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
- require File.expand_path('../lib/version', __FILE__)
3
+ require File.expand_path('../lib/rom/version', __FILE__)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = 'rom'
7
7
  gem.summary = 'Ruby Object Mapper'
8
8
  gem.description = gem.summary
9
- gem.authors = ['Piotr Solnica', 'Dan Kubb', 'Markus Schirp', 'Martin Gamsjaeger'].sort
10
- gem.email = ['piotr.solnica@gmail.com', 'dan.kubb@gmail.com', 'mbj@schirp-dso.com', 'gamsnjaga@gmail.com'].sort
9
+ gem.authors = 'Piotr Solnica',
10
+ gem.email = 'piotr.solnica@gmail.com'
11
11
  gem.homepage = 'http://rom-rb.org'
12
12
  gem.require_paths = ['lib']
13
13
  gem.version = ROM::VERSION.dup
@@ -15,11 +15,13 @@ Gem::Specification.new do |gem|
15
15
  gem.test_files = `git ls-files -- {spec}/*`.split("\n")
16
16
  gem.license = 'MIT'
17
17
 
18
- gem.add_dependency 'addressable', '~> 2.3', '>= 2.3.3'
19
- gem.add_dependency 'concord', '~> 0.1'
20
- gem.add_dependency 'adamantium', '~> 0.2'
21
- gem.add_dependency 'axiom', '~> 0.2'
22
- gem.add_dependency 'axiom-optimizer', '~> 0.2'
23
- gem.add_dependency 'charlatan', '~> 0.1'
24
- gem.add_dependency 'morpher', '~> 0.2'
18
+ gem.add_runtime_dependency 'addressable', '~> 2.3'
19
+ gem.add_runtime_dependency 'equalizer', '~> 0.0', '>= 0.0.9'
20
+ gem.add_runtime_dependency 'concord', '~> 0.1', '>= 0.1.4'
21
+ gem.add_runtime_dependency 'charlatan', '~> 0.1', '>= 0.1'
22
+ gem.add_runtime_dependency 'inflecto', '~> 0.0', '>= 0.0.2'
23
+
24
+ gem.add_development_dependency 'rake', '~> 10.3'
25
+ gem.add_development_dependency 'rspec-core', '~> 3.1'
26
+ gem.add_development_dependency 'rspec-expectations', '~> 3.1'
25
27
  end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ describe "Adapter" do
4
+ include_context "users and tasks" do
5
+ before(:all) do
6
+ Class.new(ROM::Adapter::Memory) do
7
+ def self.schemes
8
+ [:memory]
9
+ end
10
+
11
+ def extend_relation_class(klass)
12
+ klass.class_eval do
13
+ def self.freaking_awesome?
14
+ true
15
+ end
16
+ end
17
+ end
18
+
19
+ def extend_relation_instance(relation)
20
+ relation.instance_eval do
21
+ def freaking_cool?
22
+ true
23
+ end
24
+ end
25
+ end
26
+
27
+ ROM::Adapter.register(self)
28
+ end
29
+ end
30
+ end
31
+
32
+ before do
33
+ setup.relation(:users)
34
+ end
35
+
36
+ it "can extend relation class" do
37
+ expect(rom.relations.users.class).to be_freaking_awesome
38
+ end
39
+
40
+ it "can extend relation instance" do
41
+ expect(rom.relations.users).to be_freaking_cool
42
+ end
43
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Mapper definition DSL' do
4
+ include_context 'users and tasks'
5
+
6
+ let(:header) { mapper.header }
7
+
8
+ before do
9
+ setup.relation(:users) do
10
+ def email_index
11
+ project(:email)
12
+ end
13
+ end
14
+ end
15
+
16
+ describe 'default PORO mapper' do
17
+ subject(:mapper) { rom.read(:users).mapper }
18
+
19
+ before do
20
+ setup.mappers do
21
+ define(:users) do
22
+ model name: 'User'
23
+ end
24
+ end
25
+ end
26
+
27
+ it 'defines a constant for the model class' do
28
+ expect(mapper.model).to be(User)
29
+ end
30
+
31
+ it 'uses all attributes from the relation header by default' do
32
+ expect(header.keys).to eql(rom.relations.users.header)
33
+ end
34
+ end
35
+
36
+ describe 'excluding attributes' do
37
+ subject(:mapper) { rom.read(:users).mapper }
38
+
39
+ before do
40
+ setup.mappers do
41
+ define(:users) do
42
+ model name: 'User'
43
+
44
+ exclude :name
45
+ end
46
+ end
47
+ end
48
+
49
+ it 'only maps provided attributes' do
50
+ expect(header.keys).to eql([:email])
51
+ end
52
+ end
53
+
54
+ describe 'virtual relation mapper' do
55
+ subject(:mapper) { rom.read(:users).email_index.mapper }
56
+
57
+ before do
58
+ setup.mappers do
59
+ define(:users) do
60
+ model name: 'User'
61
+ end
62
+ end
63
+
64
+ setup.mappers do
65
+ define(:email_index, parent: :users) do
66
+ model name: 'UserWithoutName'
67
+ exclude :name
68
+ end
69
+ end
70
+ end
71
+
72
+ it 'inherits the attributes from the parent by default' do
73
+ expect(header.keys).to eql(rom.mappers[:users].header - [:name])
74
+ end
75
+
76
+ it 'builds a new model' do
77
+ expect(mapper.model).to be(UserWithoutName)
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Mappers / Prefixing attributes' do
4
+ let(:setup) { ROM.setup(memory: 'memory://test') }
5
+
6
+ before do
7
+ setup.schema do
8
+ base_relation(:users) do
9
+ repository :memory
10
+
11
+ attribute :user_id
12
+ attribute :user_name
13
+ attribute :user_email
14
+ end
15
+ end
16
+
17
+ setup.relation(:users)
18
+ end
19
+
20
+ it 'automatically maps all attributes using the provided prefix' do
21
+ setup.mappers do
22
+ define(:users, prefix: :user) do
23
+ model name: 'User'
24
+
25
+ attribute :id
26
+ attribute :name
27
+ attribute :email
28
+ end
29
+ end
30
+
31
+ rom = setup.finalize
32
+
33
+ User.send(:include, Equalizer.new(:id, :name, :email))
34
+
35
+ rom.schema.users << { user_id: 123, user_name: 'Jane', user_email: 'jane@doe.org' }
36
+
37
+ jane = rom.read(:users).to_a.first
38
+
39
+ expect(jane).to eql(User.new(id: 123, name: 'Jane', email: 'jane@doe.org'))
40
+ end
41
+
42
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Mappers / Renaming attributes' do
4
+ let(:setup) { ROM.setup(memory: 'memory://test') }
5
+
6
+ before do
7
+ setup.schema do
8
+ base_relation(:users) do
9
+ repository :memory
10
+
11
+ attribute :_id
12
+ attribute :user_name
13
+ end
14
+
15
+ base_relation(:addresses) do
16
+ repository :memory
17
+
18
+ attribute :address_id
19
+ attribute :address_street
20
+ end
21
+ end
22
+
23
+ setup.relation(:addresses)
24
+
25
+ setup.relation(:users) do
26
+ def with_address
27
+ in_memory {
28
+ wrap(join(users, addresses), address: [:address_id, :address_street])
29
+ }
30
+ end
31
+
32
+ def with_addresses
33
+ in_memory {
34
+ group(join(users, addresses), addresses: [:address_id, :address_street])
35
+ }
36
+ end
37
+ end
38
+ end
39
+
40
+ it 'maps renamed attributes for a base relation' do
41
+ setup.mappers do
42
+ define(:users) do
43
+ model name: 'User'
44
+
45
+ attribute :id, from: :_id
46
+ attribute :name, from: :user_name
47
+ end
48
+ end
49
+
50
+ rom = setup.finalize
51
+
52
+ User.send(:include, Equalizer.new(:id, :name))
53
+
54
+ rom.schema.users << { _id: 123, user_name: 'Jane' }
55
+
56
+ jane = rom.read(:users).to_a.first
57
+
58
+ expect(jane).to eql(User.new(id: 123, name: 'Jane'))
59
+ end
60
+
61
+ it 'maps renamed attributes for a wrapped relation' do
62
+ setup.mappers do
63
+ define(:users) do
64
+ model name: 'User'
65
+
66
+ attribute :id, from: :_id
67
+ attribute :name, from: :user_name
68
+ end
69
+
70
+ define(:with_address, parent: :users) do
71
+ model name: 'UserWithAddress'
72
+
73
+ attribute :id, from: :_id
74
+ attribute :name, from: :user_name
75
+
76
+ wrap :address do
77
+ attribute :id, from: :address_id
78
+ attribute :street, from: :address_street
79
+ end
80
+ end
81
+ end
82
+
83
+ rom = setup.finalize
84
+
85
+ UserWithAddress.send(:include, Equalizer.new(:id, :name, :address))
86
+
87
+ rom.schema.users << { _id: 123, user_name: 'Jane' }
88
+ rom.schema.addresses << { _id: 123, address_id: 321, address_street: 'Street 1' }
89
+
90
+ jane = rom.read(:users).with_address.first
91
+
92
+ expect(jane).to eql(
93
+ UserWithAddress.new(id: 123, name: 'Jane', address: { id: 321, street: 'Street 1' })
94
+ )
95
+ end
96
+
97
+ it 'maps renamed attributes for a grouped relation' do
98
+ setup.mappers do
99
+ define(:users) do
100
+ model name: 'User'
101
+
102
+ attribute :id, from: :_id
103
+ attribute :name, from: :user_name
104
+ end
105
+
106
+ define(:with_addresses, parent: :users) do
107
+ model name: 'UserWithAddresses'
108
+
109
+ attribute :id, from: :_id
110
+ attribute :name, from: :user_name
111
+
112
+ group :addresses do
113
+ attribute :id, from: :address_id
114
+ attribute :street, from: :address_street
115
+ end
116
+ end
117
+ end
118
+
119
+ rom = setup.finalize
120
+
121
+ UserWithAddresses.send(:include, Equalizer.new(:id, :name, :addresses))
122
+
123
+ rom.schema.users << { _id: 123, user_name: 'Jane' }
124
+ rom.schema.addresses << { _id: 123, address_id: 321, address_street: 'Street 1' }
125
+ rom.schema.addresses << { _id: 123, address_id: 654, address_street: 'Street 2' }
126
+
127
+ jane = rom.read(:users).with_addresses.first
128
+
129
+ expect(jane).to eql(
130
+ UserWithAddresses.new(
131
+ id: 123,
132
+ name: 'Jane',
133
+ addresses: [{ id: 321, street: 'Street 1' },
134
+ { id: 654, street: 'Street 2' }]
135
+ )
136
+ )
137
+ end
138
+ end