rom 0.2.0 → 0.3.0

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