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.
- checksums.yaml +7 -0
- data/.gitignore +3 -3
- data/.ruby-version +1 -1
- data/.travis.yml +13 -14
- data/{Changelog.md → CHANGELOG.md} +12 -3
- data/Gemfile +14 -10
- data/Gemfile.devtools +16 -16
- data/Guardfile +2 -5
- data/README.md +68 -56
- data/Rakefile +3 -3
- data/config/flay.yml +2 -2
- data/config/mutant.yml +2 -4
- data/config/rubocop.yml +30 -0
- data/lib/rom.rb +47 -9
- data/lib/rom/adapter.rb +52 -0
- data/lib/rom/adapter/memory.rb +70 -0
- data/lib/rom/boot.rb +158 -0
- data/lib/rom/boot/base_relation_dsl.rb +43 -0
- data/lib/rom/boot/dsl.rb +30 -0
- data/lib/rom/boot/mapper_dsl.rb +23 -0
- data/lib/rom/boot/relation_dsl.rb +23 -0
- data/lib/rom/boot/schema_dsl.rb +27 -0
- data/lib/rom/env.rb +48 -0
- data/lib/rom/header.rb +123 -0
- data/lib/rom/mapper.rb +38 -153
- data/lib/rom/mapper_builder.rb +85 -0
- data/lib/rom/model_builder.rb +58 -0
- data/lib/rom/ra.rb +196 -0
- data/lib/rom/ra/operation/group.rb +49 -0
- data/lib/rom/ra/operation/join.rb +41 -0
- data/lib/rom/ra/operation/wrap.rb +45 -0
- data/lib/rom/reader.rb +62 -0
- data/lib/rom/reader_builder.rb +28 -0
- data/lib/rom/relation.rb +41 -350
- data/lib/rom/relation_builder.rb +48 -0
- data/lib/rom/repository.rb +28 -53
- data/lib/rom/support/registry.rb +34 -0
- data/lib/rom/version.rb +3 -0
- data/rom.gemspec +12 -10
- data/spec/integration/adapters/extending_relations_spec.rb +43 -0
- data/spec/integration/mappers/definition_dsl_spec.rb +82 -0
- data/spec/integration/mappers/prefixing_attributes_spec.rb +42 -0
- data/spec/integration/mappers/renaming_attributes_spec.rb +138 -0
- data/spec/integration/ra/group_spec.rb +47 -0
- data/spec/integration/ra/join_spec.rb +24 -0
- data/spec/integration/ra/wrap_spec.rb +37 -0
- data/spec/integration/relations/reading_spec.rb +116 -0
- data/spec/integration/relations/registry_dsl_spec.rb +44 -0
- data/spec/integration/schema_spec.rb +29 -0
- data/spec/integration/setup_spec.rb +18 -0
- data/spec/shared/users_and_tasks.rb +34 -0
- data/spec/spec_helper.rb +14 -36
- data/spec/unit/rom/adapter_spec.rb +59 -0
- data/spec/unit/rom/header_spec.rb +58 -0
- data/spec/unit/rom/mapper_spec.rb +27 -0
- data/spec/unit/rom/ra/operation/group_spec.rb +55 -0
- data/spec/unit/rom/ra/operation/wrap_spec.rb +29 -0
- data/spec/unit/rom/relation_spec.rb +34 -0
- metadata +122 -190
- data/lib/rom/constants.rb +0 -16
- data/lib/rom/environment.rb +0 -105
- data/lib/rom/environment/builder.rb +0 -71
- data/lib/rom/mapper/attribute.rb +0 -108
- data/lib/rom/mapper/builder.rb +0 -58
- data/lib/rom/mapper/builder/definition.rb +0 -162
- data/lib/rom/mapper/header.rb +0 -103
- data/lib/rom/mapper/loader_builder.rb +0 -26
- data/lib/rom/schema.rb +0 -21
- data/lib/rom/schema/builder.rb +0 -59
- data/lib/rom/schema/definition.rb +0 -84
- data/lib/rom/schema/definition/relation.rb +0 -80
- data/lib/rom/schema/definition/relation/base.rb +0 -27
- data/lib/rom/session.rb +0 -111
- data/lib/rom/session/environment.rb +0 -67
- data/lib/rom/session/identity_map.rb +0 -43
- data/lib/rom/session/mapper.rb +0 -62
- data/lib/rom/session/relation.rb +0 -140
- data/lib/rom/session/state.rb +0 -59
- data/lib/rom/session/state/created.rb +0 -22
- data/lib/rom/session/state/deleted.rb +0 -25
- data/lib/rom/session/state/persisted.rb +0 -34
- data/lib/rom/session/state/transient.rb +0 -20
- data/lib/rom/session/state/updated.rb +0 -29
- data/lib/rom/session/tracker.rb +0 -62
- data/lib/rom/support/axiom/adapter.rb +0 -111
- data/lib/rom/support/axiom/adapter/data_objects.rb +0 -38
- data/lib/rom/support/axiom/adapter/memory.rb +0 -25
- data/lib/rom/support/axiom/adapter/postgres.rb +0 -19
- data/lib/rom/support/axiom/adapter/sqlite3.rb +0 -20
- data/lib/version.rb +0 -3
- data/spec/integration/environment_setup_spec.rb +0 -24
- data/spec/integration/grouped_mappers_spec.rb +0 -87
- data/spec/integration/join_and_group_spec.rb +0 -76
- data/spec/integration/join_and_wrap_spec.rb +0 -68
- data/spec/integration/mapping_embedded_relations_spec.rb +0 -73
- data/spec/integration/mapping_relations_spec.rb +0 -120
- data/spec/integration/schema_definition_spec.rb +0 -152
- data/spec/integration/session_spec.rb +0 -87
- data/spec/integration/wrapped_mappers_spec.rb +0 -73
- data/spec/shared/unit/environment_context.rb +0 -6
- data/spec/shared/unit/loader.rb +0 -11
- data/spec/shared/unit/loader_identity.rb +0 -13
- data/spec/shared/unit/mapper_context.rb +0 -11
- data/spec/shared/unit/relation_context.rb +0 -82
- data/spec/shared/unit/session_environment_context.rb +0 -11
- data/spec/shared/unit/session_relation_context.rb +0 -18
- data/spec/support/helper.rb +0 -34
- data/spec/support/ice_nine_config.rb +0 -10
- data/spec/support/test_mapper.rb +0 -110
- data/spec/unit/rom/environment/builder/mapping_spec.rb +0 -24
- data/spec/unit/rom/environment/builder/schema_spec.rb +0 -33
- data/spec/unit/rom/environment/class_methods/setup_spec.rb +0 -18
- data/spec/unit/rom/environment/repository_spec.rb +0 -21
- data/spec/unit/rom/mapper/attribute/embedded_collection/to_ast_spec.rb +0 -18
- data/spec/unit/rom/mapper/attribute/embedded_value/to_ast_spec.rb +0 -16
- data/spec/unit/rom/mapper/attribute/rename_spec.rb +0 -9
- data/spec/unit/rom/mapper/attribute/to_ast_spec.rb +0 -9
- data/spec/unit/rom/mapper/builder/class_methods/call_spec.rb +0 -61
- data/spec/unit/rom/mapper/class_methods/build_spec.rb +0 -55
- data/spec/unit/rom/mapper/dump_spec.rb +0 -11
- data/spec/unit/rom/mapper/group_spec.rb +0 -35
- data/spec/unit/rom/mapper/header/each_spec.rb +0 -26
- data/spec/unit/rom/mapper/header/element_reader_spec.rb +0 -21
- data/spec/unit/rom/mapper/header/group_spec.rb +0 -18
- data/spec/unit/rom/mapper/header/join_spec.rb +0 -14
- data/spec/unit/rom/mapper/header/keys_spec.rb +0 -29
- data/spec/unit/rom/mapper/header/project_spec.rb +0 -13
- data/spec/unit/rom/mapper/header/rename_spec.rb +0 -11
- data/spec/unit/rom/mapper/header/to_ast_spec.rb +0 -11
- data/spec/unit/rom/mapper/header/wrap_spec.rb +0 -18
- data/spec/unit/rom/mapper/identity_from_tuple_spec.rb +0 -11
- data/spec/unit/rom/mapper/identity_spec.rb +0 -11
- data/spec/unit/rom/mapper/join_spec.rb +0 -15
- data/spec/unit/rom/mapper/load_spec.rb +0 -11
- data/spec/unit/rom/mapper/new_object_spec.rb +0 -14
- data/spec/unit/rom/mapper/project_spec.rb +0 -11
- data/spec/unit/rom/mapper/rename_spec.rb +0 -16
- data/spec/unit/rom/mapper/wrap_spec.rb +0 -35
- data/spec/unit/rom/relation/delete_spec.rb +0 -15
- data/spec/unit/rom/relation/drop_spec.rb +0 -11
- data/spec/unit/rom/relation/each_spec.rb +0 -23
- data/spec/unit/rom/relation/first_spec.rb +0 -19
- data/spec/unit/rom/relation/group_spec.rb +0 -29
- data/spec/unit/rom/relation/inject_mapper_spec.rb +0 -17
- data/spec/unit/rom/relation/insert_spec.rb +0 -13
- data/spec/unit/rom/relation/last_spec.rb +0 -19
- data/spec/unit/rom/relation/one_spec.rb +0 -49
- data/spec/unit/rom/relation/rename_spec.rb +0 -21
- data/spec/unit/rom/relation/replace_spec.rb +0 -13
- data/spec/unit/rom/relation/restrict_spec.rb +0 -25
- data/spec/unit/rom/relation/sort_by_spec.rb +0 -25
- data/spec/unit/rom/relation/take_spec.rb +0 -11
- data/spec/unit/rom/relation/to_a_spec.rb +0 -20
- data/spec/unit/rom/relation/update_spec.rb +0 -25
- data/spec/unit/rom/relation/wrap_spec.rb +0 -29
- data/spec/unit/rom/repository/class_methods/build_spec.rb +0 -27
- data/spec/unit/rom/repository/element_reader_spec.rb +0 -21
- data/spec/unit/rom/repository/element_writer_spec.rb +0 -18
- data/spec/unit/rom/schema/builder/class_methods/build_spec.rb +0 -103
- data/spec/unit/rom/schema/element_reader_spec.rb +0 -15
- data/spec/unit/rom/session/class_methods/start_spec.rb +0 -23
- data/spec/unit/rom/session/clean_predicate_spec.rb +0 -21
- data/spec/unit/rom/session/environment/element_reader_spec.rb +0 -13
- data/spec/unit/rom/session/flush_spec.rb +0 -58
- data/spec/unit/rom/session/mapper/load_spec.rb +0 -47
- data/spec/unit/rom/session/relation/delete_spec.rb +0 -28
- data/spec/unit/rom/session/relation/dirty_predicate_spec.rb +0 -35
- data/spec/unit/rom/session/relation/identity_spec.rb +0 -11
- data/spec/unit/rom/session/relation/new_spec.rb +0 -50
- data/spec/unit/rom/session/relation/save_spec.rb +0 -50
- data/spec/unit/rom/session/relation/state_spec.rb +0 -23
- data/spec/unit/rom/session/relation/track_spec.rb +0 -23
- data/spec/unit/rom/session/relation/tracking_predicate_spec.rb +0 -23
- data/spec/unit/rom/session/relation/update_attributes_spec.rb +0 -45
- 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
|
-
|
2
|
-
|
3
|
-
require 'rom/constants'
|
1
|
+
require 'rom/ra'
|
4
2
|
|
5
3
|
module ROM
|
6
4
|
|
7
|
-
#
|
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
|
-
#
|
38
|
-
#
|
39
|
-
#
|
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
|
-
#
|
42
|
-
#
|
43
|
-
#
|
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
|
-
#
|
46
|
-
#
|
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
|
50
|
-
include Equalizer.new(:
|
51
|
-
include
|
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
|
-
|
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
|
-
|
29
|
+
# @api private
|
30
|
+
def self.finalize(env, relation)
|
31
|
+
# noop
|
311
32
|
end
|
312
33
|
|
313
|
-
#
|
314
|
-
|
315
|
-
|
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
|
-
#
|
330
|
-
|
331
|
-
|
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
|
-
#
|
343
|
-
|
344
|
-
|
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
|
361
|
-
|
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
|
370
|
-
|
59
|
+
def delete
|
60
|
+
dataset.delete
|
61
|
+
self
|
371
62
|
end
|
372
63
|
|
373
|
-
end
|
64
|
+
end
|
374
65
|
|
375
|
-
end
|
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
|