rom 0.4.2 → 0.5.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 +4 -4
- data/.rubocop.yml +81 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.md +41 -0
- data/Gemfile +12 -8
- data/Guardfile +17 -11
- data/README.md +7 -7
- data/Rakefile +29 -0
- data/lib/rom.rb +9 -66
- data/lib/rom/adapter.rb +45 -12
- data/lib/rom/adapter/memory.rb +0 -4
- data/lib/rom/adapter/memory/commands.rb +0 -10
- data/lib/rom/adapter/memory/dataset.rb +18 -6
- data/lib/rom/adapter/memory/storage.rb +0 -3
- data/lib/rom/command_registry.rb +24 -43
- data/lib/rom/commands.rb +5 -6
- data/lib/rom/commands/create.rb +5 -5
- data/lib/rom/commands/delete.rb +8 -6
- data/lib/rom/commands/result.rb +82 -0
- data/lib/rom/commands/update.rb +5 -4
- data/lib/rom/commands/with_options.rb +1 -4
- data/lib/rom/config.rb +70 -0
- data/lib/rom/env.rb +11 -3
- data/lib/rom/global.rb +107 -0
- data/lib/rom/header.rb +122 -89
- data/lib/rom/header/attribute.rb +148 -0
- data/lib/rom/mapper.rb +46 -67
- data/lib/rom/mapper_builder.rb +20 -73
- data/lib/rom/mapper_builder/mapper_dsl.rb +114 -0
- data/lib/rom/mapper_builder/model_dsl.rb +29 -0
- data/lib/rom/mapper_registry.rb +21 -0
- data/lib/rom/model_builder.rb +11 -17
- data/lib/rom/processor.rb +28 -0
- data/lib/rom/processor/transproc.rb +105 -0
- data/lib/rom/reader.rb +81 -21
- data/lib/rom/reader_builder.rb +14 -4
- data/lib/rom/relation.rb +19 -5
- data/lib/rom/relation_builder.rb +20 -6
- data/lib/rom/repository.rb +0 -2
- data/lib/rom/setup.rb +156 -0
- data/lib/rom/{boot → setup}/base_relation_dsl.rb +4 -8
- data/lib/rom/setup/command_dsl.rb +46 -0
- data/lib/rom/setup/finalize.rb +125 -0
- data/lib/rom/setup/mapper_dsl.rb +19 -0
- data/lib/rom/{boot → setup}/relation_dsl.rb +1 -4
- data/lib/rom/setup/schema_dsl.rb +33 -0
- data/lib/rom/support/registry.rb +10 -6
- data/lib/rom/version.rb +1 -1
- data/rom.gemspec +3 -1
- data/spec/integration/adapters/extending_relations_spec.rb +0 -2
- data/spec/integration/commands/create_spec.rb +2 -9
- data/spec/integration/commands/delete_spec.rb +4 -5
- data/spec/integration/commands/error_handling_spec.rb +4 -3
- data/spec/integration/commands/update_spec.rb +3 -8
- data/spec/integration/mappers/deep_embedded_spec.rb +52 -0
- data/spec/integration/mappers/definition_dsl_spec.rb +0 -118
- data/spec/integration/mappers/embedded_spec.rb +82 -0
- data/spec/integration/mappers/group_spec.rb +170 -0
- data/spec/integration/mappers/prefixing_attributes_spec.rb +2 -2
- data/spec/integration/mappers/renaming_attributes_spec.rb +8 -6
- data/spec/integration/mappers/symbolizing_attributes_spec.rb +80 -0
- data/spec/integration/mappers/wrap_spec.rb +162 -0
- data/spec/integration/multi_repo_spec.rb +64 -0
- data/spec/integration/relations/reading_spec.rb +12 -8
- data/spec/integration/relations/registry_dsl_spec.rb +1 -3
- data/spec/integration/schema_spec.rb +10 -0
- data/spec/integration/setup_spec.rb +57 -6
- data/spec/spec_helper.rb +2 -1
- data/spec/unit/config_spec.rb +60 -0
- data/spec/unit/rom/adapter/memory/dataset_spec.rb +52 -0
- data/spec/unit/rom/adapter_spec.rb +31 -11
- data/spec/unit/rom/header_spec.rb +60 -16
- data/spec/unit/rom/mapper_builder_spec.rb +311 -0
- data/spec/unit/rom/mapper_registry_spec.rb +25 -0
- data/spec/unit/rom/mapper_spec.rb +4 -5
- data/spec/unit/rom/model_builder_spec.rb +15 -13
- data/spec/unit/rom/processor/transproc_spec.rb +331 -0
- data/spec/unit/rom/reader_spec.rb +73 -0
- data/spec/unit/rom/registry_spec.rb +38 -0
- data/spec/unit/rom/relation_spec.rb +0 -1
- data/spec/unit/rom/setup_spec.rb +55 -0
- data/spec/unit/rom_spec.rb +14 -0
- metadata +62 -22
- data/Gemfile.devtools +0 -71
- data/lib/rom/boot.rb +0 -197
- data/lib/rom/boot/command_dsl.rb +0 -48
- data/lib/rom/boot/dsl.rb +0 -37
- data/lib/rom/boot/mapper_dsl.rb +0 -23
- data/lib/rom/boot/schema_dsl.rb +0 -27
- data/lib/rom/ra.rb +0 -172
- data/lib/rom/ra/operation/group.rb +0 -47
- data/lib/rom/ra/operation/join.rb +0 -39
- data/lib/rom/ra/operation/wrap.rb +0 -45
- data/lib/rom/transformer.rb +0 -77
- data/spec/integration/ra/group_spec.rb +0 -46
- data/spec/integration/ra/join_spec.rb +0 -50
- data/spec/integration/ra/wrap_spec.rb +0 -37
- data/spec/unit/rom/ra/operation/group_spec.rb +0 -55
- data/spec/unit/rom/ra/operation/wrap_spec.rb +0 -29
- data/spec/unit/rom/transformer_spec.rb +0 -41
data/lib/rom/relation_builder.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
module ROM
|
2
|
-
|
3
2
|
# @api private
|
4
3
|
class RelationBuilder
|
5
4
|
attr_reader :schema, :mod
|
6
5
|
|
7
6
|
# @api private
|
8
|
-
def initialize(schema)
|
7
|
+
def initialize(schema, relations)
|
9
8
|
@schema = schema
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
@mod = Module.new
|
11
|
+
|
12
|
+
@mod.module_exec do
|
13
|
+
define_method(:__relations__) { relations }
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
@@ -34,6 +36,20 @@ module ROM
|
|
34
36
|
def name
|
35
37
|
#{name.inspect}
|
36
38
|
end
|
39
|
+
|
40
|
+
def respond_to_missing?(name, _include_private = false)
|
41
|
+
__relations__.key?(name) || super
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def method_missing(name, *args, &block)
|
47
|
+
if __relations__.key?(name)
|
48
|
+
__relations__[name]
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
37
53
|
RUBY
|
38
54
|
|
39
55
|
klass.send(:include, mod)
|
@@ -42,7 +58,5 @@ module ROM
|
|
42
58
|
|
43
59
|
klass.new(schema_relation.dataset, schema_relation.header)
|
44
60
|
end
|
45
|
-
|
46
61
|
end
|
47
|
-
|
48
62
|
end
|
data/lib/rom/repository.rb
CHANGED
data/lib/rom/setup.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'rom/setup/schema_dsl'
|
2
|
+
require 'rom/setup/mapper_dsl'
|
3
|
+
require 'rom/setup/command_dsl'
|
4
|
+
|
5
|
+
require 'rom/setup/finalize'
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
# Exposes DSL for defining schema, relations, mappers and commands
|
9
|
+
#
|
10
|
+
# @public
|
11
|
+
class Setup
|
12
|
+
include Equalizer.new(:repositories, :env)
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
attr_reader :repositories, :env
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
def initialize(repositories)
|
19
|
+
@repositories = repositories
|
20
|
+
@schema = {}
|
21
|
+
@relations = {}
|
22
|
+
@mappers = []
|
23
|
+
@commands = {}
|
24
|
+
@adapter_relation_map = {}
|
25
|
+
@env = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
# Schema definition DSL
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
#
|
32
|
+
# setup.schema do
|
33
|
+
# base_relation(:users) do
|
34
|
+
# repository :sqlite
|
35
|
+
#
|
36
|
+
# attribute :id
|
37
|
+
# attribute :name
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def schema(&block)
|
43
|
+
SchemaDSL.new(self, @schema, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Relation definition DSL
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
#
|
50
|
+
# setup.relation(:users) do
|
51
|
+
# def names
|
52
|
+
# project(:name)
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# @api public
|
57
|
+
def relation(name, &block)
|
58
|
+
@relations.update(name => block)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Mapper definition DSL
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
#
|
65
|
+
# setup.mappers do
|
66
|
+
# define(:users) do
|
67
|
+
# model name: 'User'
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# define(:names, parent: :users) do
|
71
|
+
# exclude :id
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# @api public
|
76
|
+
def mappers(&block)
|
77
|
+
dsl = MapperDSL.new(&block)
|
78
|
+
@mappers.concat(dsl.mappers)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Command definition DSL
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
#
|
85
|
+
# setup.commands(:users) do
|
86
|
+
# define(:create) do
|
87
|
+
# input NewUserParams
|
88
|
+
# validator NewUserValidator
|
89
|
+
# result :one
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# define(:update) do
|
93
|
+
# input UserParams
|
94
|
+
# validator UserValidator
|
95
|
+
# result :many
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# define(:delete) do
|
99
|
+
# result :many
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# @api public
|
104
|
+
def commands(name, &block)
|
105
|
+
dsl = CommandDSL.new(&block)
|
106
|
+
@commands.update(name => dsl.commands)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Finalize the setup
|
110
|
+
#
|
111
|
+
# @return [Env] frozen env with access to repositories, schema, relations,
|
112
|
+
# mappers and commands
|
113
|
+
#
|
114
|
+
# @api public
|
115
|
+
def finalize
|
116
|
+
raise EnvAlreadyFinalizedError if env
|
117
|
+
|
118
|
+
finalize = Finalize.new(
|
119
|
+
repositories, @schema, @relations, @mappers, @commands
|
120
|
+
)
|
121
|
+
|
122
|
+
@env = finalize.run!
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns repository identified by name
|
126
|
+
#
|
127
|
+
# @return [Repository]
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
def [](name)
|
131
|
+
repositories.fetch(name)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Hook for respond_to? used internally
|
135
|
+
#
|
136
|
+
# @api private
|
137
|
+
def respond_to_missing?(name, _include_context = false)
|
138
|
+
repositories.key?(name)
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# Returns repository if method is a name of a registered repository
|
144
|
+
#
|
145
|
+
# @return [Repository]
|
146
|
+
#
|
147
|
+
# @api private
|
148
|
+
def method_missing(name, *)
|
149
|
+
if repositories.key?(name)
|
150
|
+
repositories.fetch(name)
|
151
|
+
else
|
152
|
+
super
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module ROM
|
2
|
-
class
|
3
|
-
|
2
|
+
class Setup
|
4
3
|
class BaseRelationDSL
|
5
4
|
attr_reader :env, :name, :header
|
6
5
|
|
7
|
-
def initialize(env, name)
|
6
|
+
def initialize(env, name, &block)
|
8
7
|
@env = env
|
9
8
|
@name = name
|
10
9
|
@header = []
|
11
10
|
@repository = nil
|
11
|
+
instance_exec(&block)
|
12
12
|
end
|
13
13
|
|
14
14
|
def repository(name = nil)
|
@@ -23,9 +23,7 @@ module ROM
|
|
23
23
|
header << name
|
24
24
|
end
|
25
25
|
|
26
|
-
def call
|
27
|
-
instance_exec(&block)
|
28
|
-
|
26
|
+
def call
|
29
27
|
dataset =
|
30
28
|
if adapter.respond_to?(:dataset)
|
31
29
|
adapter.dataset(name, header)
|
@@ -43,8 +41,6 @@ module ROM
|
|
43
41
|
def adapter
|
44
42
|
repository.adapter
|
45
43
|
end
|
46
|
-
|
47
44
|
end
|
48
|
-
|
49
45
|
end
|
50
46
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rom/mapper_builder'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
class Setup
|
5
|
+
class CommandDSL
|
6
|
+
attr_reader :commands
|
7
|
+
|
8
|
+
class CommandDefinition
|
9
|
+
attr_reader :options
|
10
|
+
|
11
|
+
def initialize(options, &block)
|
12
|
+
@options = options
|
13
|
+
instance_exec(&block) if block
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
options
|
18
|
+
end
|
19
|
+
|
20
|
+
def type
|
21
|
+
options[:type]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def method_missing(name, *args, &block)
|
27
|
+
if args.size == 1
|
28
|
+
options[name] = args.first
|
29
|
+
else
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(&block)
|
36
|
+
@commands = {}
|
37
|
+
instance_exec(&block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def define(name, options = {}, &block)
|
41
|
+
commands[name] = CommandDefinition.new(options, &block)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'rom/relation_builder'
|
2
|
+
require 'rom/reader_builder'
|
3
|
+
require 'rom/command_registry'
|
4
|
+
|
5
|
+
require 'rom/env'
|
6
|
+
|
7
|
+
module ROM
|
8
|
+
class Setup
|
9
|
+
# @private
|
10
|
+
class Finalize
|
11
|
+
attr_reader :repositories, :adapter_relation_map
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
def initialize(repositories, schema, relations, mappers, commands)
|
15
|
+
@repositories = repositories
|
16
|
+
@schema = schema
|
17
|
+
@relations = relations
|
18
|
+
@mappers = mappers
|
19
|
+
@commands = commands
|
20
|
+
@adapter_relation_map = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api private
|
24
|
+
def run!
|
25
|
+
schema = load_schema
|
26
|
+
relations = load_relations(schema)
|
27
|
+
readers = load_readers(relations)
|
28
|
+
commands = load_commands(relations)
|
29
|
+
|
30
|
+
Env.new(repositories, schema, relations, readers, commands)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
def load_schema
|
37
|
+
repositories.each_value do |repo|
|
38
|
+
(@schema[repo] ||= []).concat(repo.schema)
|
39
|
+
end
|
40
|
+
|
41
|
+
base_relations = @schema.each_with_object({}) do |(repo, schema), h|
|
42
|
+
schema.each do |name, dataset, header|
|
43
|
+
adapter_relation_map[name] = repo.adapter
|
44
|
+
h[name] = Relation.new(dataset, header)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Schema.new(base_relations)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @api private
|
52
|
+
def load_relations(schema)
|
53
|
+
return RelationRegistry.new unless adapter_relation_map.any?
|
54
|
+
|
55
|
+
relations = {}
|
56
|
+
builder = RelationBuilder.new(schema, relations)
|
57
|
+
|
58
|
+
@relations.each do |name, block|
|
59
|
+
relations[name] = build_relation(name, builder, block)
|
60
|
+
end
|
61
|
+
|
62
|
+
(schema.elements.keys - relations.keys).each do |name|
|
63
|
+
relations[name] = build_relation(name, builder)
|
64
|
+
end
|
65
|
+
|
66
|
+
relations.each_value do |relation|
|
67
|
+
relation.class.finalize(relations, relation)
|
68
|
+
end
|
69
|
+
|
70
|
+
RelationRegistry.new(relations)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
def build_relation(name, builder, block = nil)
|
75
|
+
adapter = adapter_relation_map[name]
|
76
|
+
|
77
|
+
relation = builder.call(name) do |klass|
|
78
|
+
adapter.extend_relation_class(klass)
|
79
|
+
methods = klass.public_instance_methods
|
80
|
+
|
81
|
+
klass.class_eval(&block) if block
|
82
|
+
|
83
|
+
klass.relation_methods = klass.public_instance_methods - methods
|
84
|
+
end
|
85
|
+
|
86
|
+
adapter.extend_relation_instance(relation)
|
87
|
+
|
88
|
+
relation
|
89
|
+
end
|
90
|
+
|
91
|
+
# @api private
|
92
|
+
def load_readers(relations)
|
93
|
+
return ReaderRegistry.new unless adapter_relation_map.any?
|
94
|
+
|
95
|
+
reader_builder = ReaderBuilder.new(relations)
|
96
|
+
|
97
|
+
readers = @mappers.each_with_object({}) do |(name, options, block), h|
|
98
|
+
h[name] = reader_builder.call(name, options, &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
ReaderRegistry.new(readers)
|
102
|
+
end
|
103
|
+
|
104
|
+
def load_commands(relations)
|
105
|
+
return Registry.new unless relations.elements.any?
|
106
|
+
|
107
|
+
commands = @commands.each_with_object({}) do |(name, definitions), h|
|
108
|
+
adapter = adapter_relation_map[name]
|
109
|
+
|
110
|
+
rel_commands = {}
|
111
|
+
|
112
|
+
definitions.each do |command_name, definition|
|
113
|
+
rel_commands[command_name] = adapter.command(
|
114
|
+
command_name, relations[name], definition
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
h[name] = CommandRegistry.new(rel_commands)
|
119
|
+
end
|
120
|
+
|
121
|
+
Registry.new(commands)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rom/mapper_builder'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
class Setup
|
5
|
+
class MapperDSL
|
6
|
+
attr_reader :mappers
|
7
|
+
|
8
|
+
def initialize(&block)
|
9
|
+
@mappers = []
|
10
|
+
instance_exec(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def define(name, options = {}, &block)
|
14
|
+
mappers << [name, options, block]
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|