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
@@ -0,0 +1,28 @@
1
+ module ROM
2
+
3
+ # @api private
4
+ class ReaderBuilder
5
+ attr_reader :relations, :readers
6
+
7
+ # @api private
8
+ def initialize(relations)
9
+ @relations = relations
10
+ @readers = {}
11
+ end
12
+
13
+ # @api private
14
+ def call(name, options = {}, &block)
15
+ parent = relations[options.fetch(:parent) { name }]
16
+
17
+ builder = MapperBuilder.new(name, parent, options)
18
+ builder.instance_exec(&block)
19
+ mapper = builder.call
20
+
21
+ mappers = options[:parent] ? readers.fetch(parent.name).mappers : {}
22
+
23
+ mappers[name] = mapper
24
+ readers[name] = Reader.new(name, parent, mappers) unless options[:parent]
25
+ end
26
+
27
+ end
28
+ end
data/lib/rom/relation.rb CHANGED
@@ -1,375 +1,66 @@
1
- # encoding: utf-8
2
-
3
- require 'rom/constants'
1
+ require 'rom/ra'
4
2
 
5
3
  module ROM
6
4
 
7
- # Enhanced ROM relation wrapping axiom relation and using injected mapper to
8
- # load/dump tuples/objects
9
- #
10
- # @example
11
- #
12
- # # set up an axiom relation
13
- # header = [[:id, Integer], [:name, String]]
14
- # data = [[1, 'John'], [2, 'Jane']]
15
- # axiom = Axiom::Relation.new(header, data)
16
- #
17
- # # provide a simple mapper
18
- # class Mapper < Struct.new(:header)
19
- # def load(tuple)
20
- # data = header.map { |attribute|
21
- # [attribute.name, tuple[attribute.name]]
22
- # }
23
- # Hash[data]
24
- # end
25
- #
26
- # def dump(hash)
27
- # header.each_with_object([]) { |attribute, tuple|
28
- # tuple << hash[attribute.name]
29
- # }
30
- # end
31
- # end
32
- #
33
- # # wrap axiom relation with ROM relation
34
- # mapper = Mapper.new(axiom.header)
35
- # relation = ROM::Relation.new(axiom, mapper)
5
+ # Base relation class
36
6
  #
37
- # # relation is an enumerable and it uses mapper to load/dump tuples/objects
38
- # relation.to_a
39
- # # => [{:id=>1, :name=>'John'}, {:id=>2, :name=>'Jane'}]
7
+ # Relation is a proxy for the dataset object provided by the adapter, it
8
+ # forwards every method to the dataset that's why "native" interface of the
9
+ # underlying adapter is available in the relation. This interface, however, is
10
+ # considered to private and should not be used outside of the relation instance.
40
11
  #
41
- # # you can insert/update/delete objects
42
- # relation.insert(id: 3, name: 'Piotr').to_a
43
- # # => [{:id=>1, :name=>"John"}, {:id=>2, :name=>"Jane"}, {:id=>3, :name=>"Piotr"}]
12
+ # ROM builds sub-classes of this class for every relation defined in the env
13
+ # for easy inspection and extensibility - every adapter can provide extensions
14
+ # for those sub-classes but there is always a vanilla relation instance stored
15
+ # in the schema registry.
44
16
  #
45
- # relation.delete(id: 1, name: 'John').to_a
46
- # # => [{:id=>2, :name=>"Jane"}]
17
+ # Relation instances also have access to the experimental ROM::RA interface
18
+ # giving in-memory relational operations that are very handy, especially when
19
+ # dealing with joined relations or data coming from different sources.
47
20
  #
21
+ # @api public
48
22
  class Relation
49
- include Enumerable
50
- include Equalizer.new(:mapper)
51
- include Charlatan.new(:relation, :kind => Axiom::Relation)
52
-
53
- undef_method :sort_by
54
-
55
- attr_reader :mapper
56
-
57
- def initialize(relation, mapper)
58
- super(relation, mapper)
59
- @mapper = mapper
60
- end
61
-
62
- # Iterate over tuples yielded by the wrapped relation
63
- #
64
- # @example
65
- # mapper = Class.new {
66
- # def load(value)
67
- # value.to_s
68
- # end
69
- #
70
- # def dump(value)
71
- # value.to_i
72
- # end
73
- # }.new
74
- #
75
- # relation = ROM::Relation.new([1, 2, 3], mapper)
76
- #
77
- # relation.each do |value|
78
- # puts value # => '1'
79
- # end
80
- #
81
- # @yieldparam [Object]
82
- #
83
- # @return [Relation]
84
- #
85
- # @api public
86
- def each
87
- return to_enum unless block_given?
88
- relation.each { |tuple| yield(mapper.load(tuple)) }
89
- self
90
- end
91
-
92
- # Insert an object into relation
93
- #
94
- # @example
95
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
96
- # relation = ROM::Relation.new(axiom, mapper)
97
- #
98
- # relation.insert(id: 3)
99
- # relation.to_a # => [[1], [2], [3]]
100
- #
101
- # @param [Object]
102
- #
103
- # @return [Relation]
104
- #
105
- # @api public
106
- def insert(object)
107
- new(relation.insert([mapper.dump(object)]))
108
- end
109
- alias_method :<<, :insert
110
-
111
- # Update an object
112
- #
113
- # @example
114
- # data = [[1, 'John'], [2, 'Jane']]
115
- # axiom = Axiom::Relation.new([[:id, Integer], [:name, String]], data)
116
- # relation = ROM::Relation.new(axiom, mapper)
117
- #
118
- # relation.update({id: 2, name: 'Jane Doe'}, {id:2, name: 'Jane'})
119
- # relation.to_a # => [[1, 'John'], [2, 'Jane Doe']]
120
- #
121
- # @param [Object]
122
- # @param [Hash] original attributes
123
- #
124
- # @return [Relation]
125
- #
126
- # @api public
127
- def update(object, original_tuple)
128
- new(relation.delete([original_tuple]).insert([mapper.dump(object)]))
129
- end
130
-
131
- # Delete an object from the relation
132
- #
133
- # @example
134
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
135
- # relation = ROM::Relation.new(axiom, mapper)
136
- #
137
- # relation.delete(id: 1)
138
- # relation.to_a # => [[2]]
139
- #
140
- # @param [Object]
141
- #
142
- # @return [Relation]
143
- #
144
- # @api public
145
- def delete(object)
146
- new(relation.delete([mapper.dump(object)]))
147
- end
148
-
149
- # Replace all objects in the relation with new ones
150
- #
151
- # @example
152
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
153
- # relation = ROM::Relation.new(axiom, mapper)
154
- #
155
- # relation.replace([{id: 3}, {id: 4}])
156
- # relation.to_a # => [[3], [4]]
157
- #
158
- # @param [Array<Object>]
159
- #
160
- # @return [Relation]
161
- #
162
- # @api public
163
- def replace(objects)
164
- new(relation.replace(objects.map(&mapper.method(:dump))))
165
- end
166
-
167
- # Take objects form the relation with provided limit
168
- #
169
- # @example
170
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
171
- # relation = ROM::Relation.new(axiom, mapper)
172
- #
173
- # relation.take(2).to_a # => [[2]]
174
- #
175
- # @param [Integer] limit
176
- #
177
- # @return [Relation]
178
- #
179
- # @api public
180
- def take(limit)
181
- new(sorted.take(limit))
182
- end
183
-
184
- # Take first n-objects from the relation
185
- #
186
- # @example
187
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
188
- # relation = ROM::Relation.new(axiom, mapper)
189
- #
190
- # relation.first.to_a # => [[1]]
191
- # relation.first(2).to_a # => [[1], [2]]
192
- #
193
- # @param [Integer]
194
- #
195
- # @return [Relation]
196
- #
197
- # @api public
198
- def first(limit = 1)
199
- new(sorted.first(limit))
200
- end
201
-
202
- # Take last n-objects from the relation
203
- #
204
- # @example
205
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
206
- # relation = ROM::Relation.new(axiom, mapper)
207
- #
208
- # relation.last.to_a # => [[2]]
209
- # relation.last(2).to_a # => [[1], [2]]
210
- #
211
- # @param [Integer] limit
212
- #
213
- # @return [Relation]
214
- #
215
- # @api public
216
- def last(limit = 1)
217
- new(sorted.last(limit))
218
- end
219
-
220
- # Drop objects from the relation by the given offset
221
- #
222
- # @example
223
- # axiom = Axiom::Relation.new([[:id, Integer]], [[1], [2]])
224
- # relation = ROM::Relation.new(axiom, mapper)
225
- #
226
- # relation.drop(1).to_a # => [[2]]
227
- #
228
- # @param [Integer]
229
- #
230
- # @return [Relation]
231
- #
232
- # @api public
233
- def drop(offset)
234
- new(sorted.drop(offset))
235
- end
236
-
237
- # Return exactly one object matching criteria or raise an error
238
- #
239
- # @example
240
- # axiom = Axiom::Relation.new([[:id, Integer]], [1]])
241
- # relation = ROM::Relation.new(axiom, mapper)
242
- #
243
- # relation.one.to_a # => {id: 1}
244
- #
245
- # @param [Proc] block
246
- # optional block to call in case no tuple is returned
247
- #
248
- # @return [Object]
249
- #
250
- # @raise NoTuplesError
251
- # if no tuples were returned
252
- #
253
- # @raise ManyTuplesError
254
- # if more than one tuple was returned
255
- #
256
- # @api public
257
- def one(&block)
258
- block ||= ->() { raise NoTuplesError }
259
- tuples = take(2).to_a
260
-
261
- if tuples.count > 1
262
- raise ManyTuplesError
263
- else
264
- tuples.first || block.call
265
- end
266
- end
267
-
268
- # Inject a new mapper into this relation
269
- #
270
- # @example
271
- #
272
- # relation = ROM::Relation.new([], mapper)
273
- # relation.inject_mapper(new_mapper)
274
- #
275
- # @param [Object] a mapper object
276
- #
277
- # @return [Relation]
278
- #
279
- # @api public
280
- def inject_mapper(mapper)
281
- new(relation, mapper)
282
- end
283
-
284
- # Join two relations
285
- #
286
- # @example
287
- #
288
- # users.join(tasks)
289
- #
290
- # @return [Relation]
291
- #
292
- # @api public
293
- def join(other)
294
- new(relation.join(other.relation), mapper.join(other.mapper))
295
- end
23
+ include Charlatan.new(:dataset)
24
+ include Equalizer.new(:header, :dataset)
25
+ include RA
296
26
 
297
- # Wrap one or more relation
298
- #
299
- # @example
300
- #
301
- # tasks.join(users).wrap(user: tasks)
302
- #
303
- # @return [Relation]
304
- #
305
- # @api public
306
- def wrap(other)
307
- relation_wrap = other.each_with_object({}) { |(name, relation), o| o[name] = relation.header }
308
- mapper_wrap = other.each_with_object({}) { |(name, relation), o| o[name] = relation.mapper }
27
+ attr_reader :header
309
28
 
310
- new(relation.wrap(relation_wrap), mapper.wrap(mapper_wrap))
29
+ # @api private
30
+ def self.finalize(env, relation)
31
+ # noop
311
32
  end
312
33
 
313
- # Group one or more relation
314
- #
315
- # @example
316
- #
317
- # users.join(tasks).group(tasks: tasks)
318
- #
319
- # @return [Relation]
320
- #
321
- # @api public
322
- def group(other)
323
- relation_group = other.each_with_object({}) { |(name, relation), o| o[name] = relation.header }
324
- mapper_group = other.each_with_object({}) { |(name, relation), o| o[name] = relation.mapper }
325
-
326
- new(relation.group(relation_group), mapper.group(mapper_group))
34
+ # @api private
35
+ def initialize(dataset, header = dataset.header)
36
+ super
37
+ @header = header.dup.freeze
327
38
  end
328
39
 
329
- # Project a relation
330
- #
331
- # @example
332
- #
333
- # users.project([:id, :name])
334
- #
335
- # @return [Relation]
336
- #
337
- # @api public
338
- def project(names)
339
- new(relation.project(names), mapper.project(names))
40
+ # @api private
41
+ def each(&block)
42
+ return to_enum unless block
43
+ dataset.each(&block)
340
44
  end
341
45
 
342
- # Rename attributes in a relation
343
- #
344
- # @example
345
- #
346
- # users.rename(:user_id => :id)
347
- #
348
- # @return [Relation]
349
- #
350
- # @api public
351
- def rename(names)
352
- new(relation.rename(names), mapper.rename(names))
46
+ # @api private
47
+ def insert(tuple)
48
+ dataset.insert(tuple)
49
+ self
353
50
  end
354
51
 
355
- # Sort wrapped relation using all attributes in the header
356
- #
357
- # @return [Axiom::Relation]
358
- #
359
52
  # @api private
360
- def sorted
361
- relation.sort
53
+ def update(tuple)
54
+ dataset.update(tuple)
55
+ self
362
56
  end
363
57
 
364
- # Return new relation instance
365
- #
366
- # @return [Relation]
367
- #
368
58
  # @api private
369
- def new(new_relation, new_mapper = mapper)
370
- self.class.new(new_relation, new_mapper)
59
+ def delete
60
+ dataset.delete
61
+ self
371
62
  end
372
63
 
373
- end # class Relation
64
+ end
374
65
 
375
- end # module ROM
66
+ end
@@ -0,0 +1,48 @@
1
+ module ROM
2
+
3
+ # @api private
4
+ class RelationBuilder
5
+ attr_reader :schema, :mod
6
+
7
+ # @api private
8
+ def initialize(schema)
9
+ @schema = schema
10
+ @mod = schema.each_with_object(Module.new) do |(name, relation), m|
11
+ m.send(:define_method, name) { relation.dataset }
12
+ end
13
+ end
14
+
15
+ # @api private
16
+ def call(name)
17
+ schema_relation = schema[name]
18
+
19
+ klass = Class.new(Relation)
20
+
21
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
22
+ def self.name
23
+ "#{Relation.name}[#{Inflecto.camelize(name)}]"
24
+ end
25
+
26
+ def self.inspect
27
+ name
28
+ end
29
+
30
+ def self.to_s
31
+ name
32
+ end
33
+
34
+ def name
35
+ #{name.inspect}
36
+ end
37
+ RUBY
38
+
39
+ klass.send(:include, mod)
40
+
41
+ yield(klass)
42
+
43
+ klass.new(schema_relation.dataset, schema_relation.header)
44
+ end
45
+
46
+ end
47
+
48
+ end