rom 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,27 @@
|
|
1
|
+
require 'rom/boot/base_relation_dsl'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
class Boot
|
5
|
+
|
6
|
+
class SchemaDSL
|
7
|
+
attr_reader :env, :schema
|
8
|
+
|
9
|
+
def initialize(env, schema = {})
|
10
|
+
@env = env
|
11
|
+
@schema = schema
|
12
|
+
end
|
13
|
+
|
14
|
+
def base_relation(name, &block)
|
15
|
+
dsl = BaseRelationDSL.new(env, name)
|
16
|
+
definition = dsl.call(&block)
|
17
|
+
(schema[dsl.repository] ||= []) << definition
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
schema
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/rom/env.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module ROM
|
2
|
+
|
3
|
+
# Exposes defined repositories, schema, relations and mappers
|
4
|
+
#
|
5
|
+
# @api public
|
6
|
+
class Env
|
7
|
+
include Adamantium::Flat
|
8
|
+
|
9
|
+
attr_reader :repositories, :schema, :relations, :mappers
|
10
|
+
|
11
|
+
# @api private
|
12
|
+
def initialize(repositories, schema, relations, mappers)
|
13
|
+
@repositories = repositories
|
14
|
+
@schema = schema
|
15
|
+
@relations = relations
|
16
|
+
@mappers = mappers
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a reader with access to defined mappers
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
#
|
23
|
+
# rom.read(:users).adults.to_a
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def read(name)
|
27
|
+
mappers[name]
|
28
|
+
end
|
29
|
+
|
30
|
+
# @api private
|
31
|
+
def [](name)
|
32
|
+
repositories.fetch(name)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def respond_to_missing?(name, include_private = false)
|
37
|
+
repositories.key?(name)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
def method_missing(name, *args)
|
44
|
+
repositories.fetch(name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/rom/header.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module ROM
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
class Header
|
5
|
+
include Enumerable
|
6
|
+
include Equalizer.new(:attributes)
|
7
|
+
|
8
|
+
attr_reader :attributes
|
9
|
+
|
10
|
+
class Attribute
|
11
|
+
include Equalizer.new(:name, :key, :type)
|
12
|
+
|
13
|
+
attr_reader :name, :key, :meta
|
14
|
+
|
15
|
+
class Embedded < Attribute
|
16
|
+
include Equalizer.new(:name, :type, :model, :header)
|
17
|
+
|
18
|
+
def model
|
19
|
+
meta[:model]
|
20
|
+
end
|
21
|
+
|
22
|
+
def header
|
23
|
+
meta.fetch(:header)
|
24
|
+
end
|
25
|
+
|
26
|
+
def mapping
|
27
|
+
[name, header.mapping]
|
28
|
+
end
|
29
|
+
|
30
|
+
def embedded?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.[](type)
|
37
|
+
if type == Array || type == Hash
|
38
|
+
Embedded
|
39
|
+
else
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.coerce(input)
|
45
|
+
if input.kind_of?(self)
|
46
|
+
input
|
47
|
+
else
|
48
|
+
name = input[0]
|
49
|
+
meta = (input[1] || {}).dup
|
50
|
+
|
51
|
+
meta[:type] ||= Object
|
52
|
+
|
53
|
+
if meta.key?(:header)
|
54
|
+
meta[:header] = Header.coerce(meta[:header])
|
55
|
+
end
|
56
|
+
|
57
|
+
self[meta[:type]].new(name, meta)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize(name, meta = {})
|
62
|
+
@name = name
|
63
|
+
@meta = meta
|
64
|
+
@key = meta.fetch(:from) { name }
|
65
|
+
end
|
66
|
+
|
67
|
+
def type
|
68
|
+
meta.fetch(:type)
|
69
|
+
end
|
70
|
+
|
71
|
+
def aliased?
|
72
|
+
key != name
|
73
|
+
end
|
74
|
+
|
75
|
+
def embedded?
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
def mapping
|
80
|
+
[key, name]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.coerce(input)
|
85
|
+
if input.kind_of?(self)
|
86
|
+
input
|
87
|
+
else
|
88
|
+
attributes = input.each_with_object({}) { |pair, h|
|
89
|
+
h[pair.first] = Attribute.coerce(pair)
|
90
|
+
}
|
91
|
+
|
92
|
+
new(attributes)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def initialize(attributes)
|
97
|
+
@attributes = attributes
|
98
|
+
end
|
99
|
+
|
100
|
+
def each(&block)
|
101
|
+
return to_enum unless block
|
102
|
+
attributes.values.each(&block)
|
103
|
+
end
|
104
|
+
|
105
|
+
def keys
|
106
|
+
attributes.keys
|
107
|
+
end
|
108
|
+
|
109
|
+
def mapping
|
110
|
+
Hash[map(&:mapping)]
|
111
|
+
end
|
112
|
+
|
113
|
+
def values
|
114
|
+
attributes.values
|
115
|
+
end
|
116
|
+
|
117
|
+
def [](name)
|
118
|
+
attributes.fetch(name)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
data/lib/rom/mapper.rb
CHANGED
@@ -1,176 +1,61 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
require 'rom/constants'
|
6
|
-
require 'rom/mapper/header'
|
7
|
-
require 'rom/mapper/loader_builder'
|
8
|
-
|
9
1
|
module ROM
|
10
2
|
|
11
|
-
#
|
12
|
-
#
|
3
|
+
# @api private
|
13
4
|
class Mapper
|
14
|
-
|
15
|
-
|
16
|
-
DEFAULT_LOADER = :load_instance_variables
|
17
|
-
|
18
|
-
attr_reader :header, :loader, :dumper, :model, :type, :options
|
5
|
+
attr_reader :header, :model
|
19
6
|
|
20
|
-
|
21
|
-
|
22
|
-
# @example
|
23
|
-
#
|
24
|
-
# User = Class.new { attr_reader :id, :name }
|
25
|
-
#
|
26
|
-
# mapper = ROM::Mapper.build([[:id, from: :user_id], [:name, from: :user_name]], model: User)
|
27
|
-
#
|
28
|
-
# user = mapper.load(user_id: 1, user_name: 'Jane')
|
29
|
-
# # => #<User:0x007fee3b8bf2c8 @id=1, @name="Jane">
|
30
|
-
#
|
31
|
-
# tuple = mapper.dump(user)
|
32
|
-
# # => [1, "Jane"]
|
33
|
-
#
|
34
|
-
# @return [Mapper]
|
35
|
-
#
|
36
|
-
# @api public
|
37
|
-
def self.build(attributes, options = EMPTY_HASH)
|
38
|
-
defaults = { type: DEFAULT_LOADER, model: OpenStruct }.update(options)
|
7
|
+
class Basic < Mapper
|
8
|
+
attr_reader :mapping
|
39
9
|
|
40
|
-
header
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
# @api private
|
47
|
-
def initialize(header, loader, options)
|
48
|
-
@header = header
|
49
|
-
@loader = loader
|
50
|
-
@dumper = loader.inverse
|
51
|
-
@model = options.fetch(:model)
|
52
|
-
@type = options.fetch(:type)
|
53
|
-
@options = options
|
54
|
-
end
|
55
|
-
|
56
|
-
# Retrieve identity from the given object
|
57
|
-
#
|
58
|
-
# @example
|
59
|
-
#
|
60
|
-
# mapper.identity(user) # => [1]
|
61
|
-
#
|
62
|
-
# @param [Object]
|
63
|
-
#
|
64
|
-
# @return [Array]
|
65
|
-
#
|
66
|
-
# @api public
|
67
|
-
def identity(object)
|
68
|
-
header.keys.map { |key| object.send(key.name) }
|
69
|
-
end
|
70
|
-
|
71
|
-
# Return identity from the given tuple
|
72
|
-
#
|
73
|
-
# @example
|
74
|
-
#
|
75
|
-
# mapper.identity_from_tuple({id: 1}) # => [1]
|
76
|
-
#
|
77
|
-
# @param [Axiom::Tuple,Hash]
|
78
|
-
#
|
79
|
-
# @return [Array]
|
80
|
-
#
|
81
|
-
# @api public
|
82
|
-
def identity_from_tuple(tuple)
|
83
|
-
header.keys.map { |key| tuple[key.name] }
|
84
|
-
end
|
10
|
+
def initialize(header, model)
|
11
|
+
super
|
12
|
+
@mapping = header.mapping
|
13
|
+
end
|
85
14
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
# mapper = Mapper.build(header, User)
|
91
|
-
# mapper.new_object(id: 1, name: 'Jane') # => #<User @id=1 @name="Jane">
|
92
|
-
#
|
93
|
-
# @api public
|
94
|
-
def new_object(*args, &block)
|
95
|
-
model.new(*args, &block)
|
96
|
-
end
|
15
|
+
def load(tuple, mapping = self.mapping)
|
16
|
+
model.new(Hash[call(tuple, mapping)])
|
17
|
+
end
|
97
18
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def load(tuple)
|
102
|
-
loader.call(tuple)
|
19
|
+
def call(tuple, mapping = self.mapping)
|
20
|
+
tuple.map { |key, value| [mapping[key], value] }
|
21
|
+
end
|
103
22
|
end
|
104
23
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
def dump(object)
|
112
|
-
ary = dumper.call(object)
|
113
|
-
|
114
|
-
ary.each_with_object([]) do |(name, value), tuple|
|
115
|
-
attribute = header.detect { |attr| attr.tuple_key == name }
|
116
|
-
|
117
|
-
if attribute.respond_to?(:header)
|
118
|
-
names = attribute.header.attribute_names
|
119
|
-
|
120
|
-
if value.is_a?(Hash)
|
121
|
-
tuple << value.values_at(*names)
|
122
|
-
elsif value.is_a?(Array)
|
123
|
-
tuple << value.map { |v| v.values_at(*names) }
|
24
|
+
class Recursive < Basic
|
25
|
+
def call(tuple, mapping = self.mapping)
|
26
|
+
tuple.map do |key, value|
|
27
|
+
case value
|
28
|
+
when Hash then [key, Hash[call(value, mapping[key])]]
|
29
|
+
when Array then [key, value.map { |v| Hash[call(v, mapping[key])] }]
|
124
30
|
else
|
125
|
-
|
31
|
+
[mapping[key], value]
|
126
32
|
end
|
127
|
-
else
|
128
|
-
tuple << value
|
129
33
|
end
|
130
34
|
end
|
131
35
|
end
|
132
36
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
# otherwise header is coupled to mapper
|
143
|
-
#
|
144
|
-
# @api public
|
145
|
-
def group(other)
|
146
|
-
new(header.group(other))
|
147
|
-
end
|
148
|
-
|
149
|
-
# @api public
|
150
|
-
def join(other)
|
151
|
-
new(header.join(other.header))
|
152
|
-
end
|
153
|
-
|
154
|
-
# @api public
|
155
|
-
def project(names)
|
156
|
-
new(header.project(names))
|
157
|
-
end
|
37
|
+
def self.build(header, model)
|
38
|
+
klass =
|
39
|
+
if header.any? { |attribute| attribute.embedded? }
|
40
|
+
Recursive
|
41
|
+
elsif header.any? { |attribute| attribute.aliased? }
|
42
|
+
Basic
|
43
|
+
else
|
44
|
+
self
|
45
|
+
end
|
158
46
|
|
159
|
-
|
160
|
-
def rename(names)
|
161
|
-
new(header.rename(names))
|
47
|
+
klass.new(header, model)
|
162
48
|
end
|
163
49
|
|
164
|
-
|
165
|
-
|
166
|
-
|
50
|
+
def initialize(header, model)
|
51
|
+
@header = header
|
52
|
+
@model = model
|
167
53
|
end
|
168
54
|
|
169
|
-
|
170
|
-
|
171
|
-
self.class.build(new_header, options)
|
55
|
+
def load(tuple)
|
56
|
+
model.new(tuple)
|
172
57
|
end
|
173
58
|
|
174
|
-
end
|
59
|
+
end
|
175
60
|
|
176
|
-
end
|
61
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rom/model_builder'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
|
5
|
+
# @api private
|
6
|
+
class MapperBuilder
|
7
|
+
|
8
|
+
class AttributeDSL
|
9
|
+
attr_reader :attributes
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@attributes = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def header
|
16
|
+
Header.coerce(attributes)
|
17
|
+
end
|
18
|
+
|
19
|
+
def attribute(name, options)
|
20
|
+
attributes << [name, options]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :name, :root, :prefix,
|
25
|
+
:model_builder, :model_class, :attributes
|
26
|
+
|
27
|
+
def initialize(name, root, options = {})
|
28
|
+
@name = name
|
29
|
+
@root = root
|
30
|
+
@prefix = options[:prefix]
|
31
|
+
@attributes = root.header.map { |attr| [prefix ? :"#{prefix}_#{attr}" : attr] }
|
32
|
+
end
|
33
|
+
|
34
|
+
def model(options)
|
35
|
+
if options.is_a?(Class)
|
36
|
+
@model_class = options
|
37
|
+
else
|
38
|
+
@model_builder = ModelBuilder[options.fetch(:type) { :poro }].new(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def attribute(name, options = {})
|
45
|
+
options[:from] = :"#{prefix}_#{name}" if prefix
|
46
|
+
attributes << [name, options]
|
47
|
+
end
|
48
|
+
|
49
|
+
def exclude(name)
|
50
|
+
attributes.delete([name])
|
51
|
+
end
|
52
|
+
|
53
|
+
def group(options, &block)
|
54
|
+
attribute_dsl(options, Array, &block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def wrap(options, &block)
|
58
|
+
attribute_dsl(options, Hash, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def call
|
62
|
+
header = Header.coerce(attributes)
|
63
|
+
|
64
|
+
@model_class = model_builder.call(header) if model_builder
|
65
|
+
|
66
|
+
Mapper.build(header, model_class)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def attribute_dsl(options, type, &block)
|
72
|
+
if block
|
73
|
+
dsl = AttributeDSL.new
|
74
|
+
dsl.instance_exec(&block)
|
75
|
+
attributes << [options, header: dsl.header, type: type]
|
76
|
+
else
|
77
|
+
options.each do |name, header|
|
78
|
+
attributes << [name, header: header.zip, type: type]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|