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
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rom/setup/base_relation_dsl'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
class Setup
|
5
|
+
# @private
|
6
|
+
class SchemaDSL
|
7
|
+
attr_reader :env, :schema
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
def initialize(env, schema, &block)
|
11
|
+
@env = env
|
12
|
+
@schema = schema
|
13
|
+
initialize_schema
|
14
|
+
instance_exec(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @api public
|
18
|
+
def base_relation(name, &block)
|
19
|
+
dsl = BaseRelationDSL.new(env, name, &block)
|
20
|
+
schema[dsl.repository] << dsl.call
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
def initialize_schema
|
27
|
+
env.repositories.each_value do |repository|
|
28
|
+
schema[repository] ||= []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/rom/support/registry.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
module ROM
|
2
|
-
|
3
2
|
# @api private
|
4
3
|
class Registry
|
5
4
|
include Enumerable
|
6
5
|
include Equalizer.new(:elements)
|
7
6
|
|
8
|
-
|
7
|
+
class ElementNotFoundError < KeyError
|
8
|
+
def initialize(key, name)
|
9
|
+
super("#{key.inspect} doesn't exist in #{name} registry")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :elements, :name
|
9
14
|
|
10
15
|
def initialize(elements = {})
|
11
16
|
@elements = elements
|
17
|
+
@name = self.class.name
|
12
18
|
end
|
13
19
|
|
14
20
|
def each(&block)
|
@@ -16,8 +22,8 @@ module ROM
|
|
16
22
|
elements.each(&block)
|
17
23
|
end
|
18
24
|
|
19
|
-
def [](
|
20
|
-
elements.fetch(name)
|
25
|
+
def [](key)
|
26
|
+
elements.fetch(key) { raise ElementNotFoundError.new(key, name) }
|
21
27
|
end
|
22
28
|
|
23
29
|
def respond_to_missing?(name, include_private = false)
|
@@ -33,7 +39,5 @@ module ROM
|
|
33
39
|
super
|
34
40
|
end
|
35
41
|
end
|
36
|
-
|
37
42
|
end
|
38
|
-
|
39
43
|
end
|
data/lib/rom/version.rb
CHANGED
data/rom.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.name = 'rom'
|
7
7
|
gem.summary = 'Ruby Object Mapper'
|
8
8
|
gem.description = 'Persistence and mapping toolkit for Ruby'
|
9
|
-
gem.
|
9
|
+
gem.author = 'Piotr Solnica'
|
10
10
|
gem.email = 'piotr.solnica@gmail.com'
|
11
11
|
gem.homepage = 'http://rom-rb.org'
|
12
12
|
gem.require_paths = ['lib']
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.license = 'MIT'
|
17
17
|
|
18
18
|
gem.add_runtime_dependency 'addressable', '~> 2.3'
|
19
|
+
gem.add_runtime_dependency 'transproc', '~> 0.1'
|
19
20
|
gem.add_runtime_dependency 'equalizer', '~> 0.0', '>= 0.0.9'
|
20
21
|
gem.add_runtime_dependency 'concord', '~> 0.1', '>= 0.1.4'
|
21
22
|
gem.add_runtime_dependency 'charlatan', '~> 0.1', '>= 0.1'
|
@@ -23,5 +24,6 @@ Gem::Specification.new do |gem|
|
|
23
24
|
|
24
25
|
gem.add_development_dependency 'rake', '~> 10.3'
|
25
26
|
gem.add_development_dependency 'rspec-core', '~> 3.1'
|
27
|
+
gem.add_development_dependency 'rspec-mocks', '~> 3.1'
|
26
28
|
gem.add_development_dependency 'rspec-expectations', '~> 3.1'
|
27
29
|
end
|
@@ -29,7 +29,6 @@ describe 'Commands / Create' do
|
|
29
29
|
setup.commands(:tasks) do
|
30
30
|
define(:create)
|
31
31
|
end
|
32
|
-
|
33
32
|
end
|
34
33
|
|
35
34
|
it 'inserts user on successful validation' do
|
@@ -47,7 +46,8 @@ describe 'Commands / Create' do
|
|
47
46
|
}
|
48
47
|
}
|
49
48
|
|
50
|
-
expect(result)
|
49
|
+
expect(result)
|
50
|
+
.to match_array([{ name: 'Piotr', title: 'Finish command-api' }])
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'returns validation object with errors on failed validation' do
|
@@ -59,14 +59,11 @@ describe 'Commands / Create' do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
describe '"result" option' do
|
62
|
-
|
63
62
|
it 'returns a single tuple when set to :one' do
|
64
63
|
setup.commands(:users) do
|
65
|
-
|
66
64
|
define(:create_one, type: :create) do
|
67
65
|
result :one
|
68
66
|
end
|
69
|
-
|
70
67
|
end
|
71
68
|
|
72
69
|
tuple = { name: 'Piotr', email: 'piotr@solnic.eu' }
|
@@ -80,17 +77,13 @@ describe 'Commands / Create' do
|
|
80
77
|
|
81
78
|
it 'allows only valid result types' do
|
82
79
|
expect {
|
83
|
-
|
84
80
|
setup.commands(:users) do
|
85
81
|
define(:create_one, type: :create) do
|
86
82
|
result :invalid_type
|
87
83
|
end
|
88
84
|
end
|
89
85
|
setup.finalize
|
90
|
-
|
91
86
|
}.to raise_error(ROM::InvalidOptionError)
|
92
87
|
end
|
93
|
-
|
94
88
|
end
|
95
|
-
|
96
89
|
end
|
@@ -27,13 +27,13 @@ describe 'Commands / Delete' do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'deletes tuples matching restriction' do
|
30
|
-
result = users.try { delete(:by_name, 'Joe')
|
30
|
+
result = users.try { delete(:by_name, 'Joe') }
|
31
31
|
|
32
32
|
expect(result).to match_array([{ name: 'Joe', email: 'joe@doe.org' }])
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'returns untouched relation if there are no tuples to delete' do
|
36
|
-
result = users.try { delete(:by_name, 'Not here')
|
36
|
+
result = users.try { delete(:by_name, 'Not here') }
|
37
37
|
|
38
38
|
expect(result).to match_array([])
|
39
39
|
end
|
@@ -45,12 +45,12 @@ describe 'Commands / Delete' do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
result = users.try { delete_one(:by_name, 'Jane')
|
48
|
+
result = users.try { delete_one(:by_name, 'Jane') }
|
49
49
|
|
50
50
|
expect(result.value).to eql(name: 'Jane', email: 'jane@doe.org')
|
51
51
|
end
|
52
52
|
|
53
|
-
it 'raises
|
53
|
+
it 'raises when result is set to :one and relation contains more tuples' do
|
54
54
|
setup.commands(:users) do
|
55
55
|
define(:delete) do
|
56
56
|
result :one
|
@@ -66,5 +66,4 @@ describe 'Commands / Delete' do
|
|
66
66
|
{ name: 'Joe', email: 'joe@doe.org' }
|
67
67
|
])
|
68
68
|
end
|
69
|
-
|
70
69
|
end
|
@@ -12,12 +12,13 @@ describe 'Commands / Error handling' do
|
|
12
12
|
|
13
13
|
it 'rescues from ROM::CommandError' do
|
14
14
|
result = false
|
15
|
-
expect(users.try { raise ROM::CommandError } >->
|
16
|
-
to be_instance_of(ROM::Result::Failure)
|
15
|
+
expect(users.try { raise ROM::CommandError } >-> _test { result = true })
|
16
|
+
.to be_instance_of(ROM::Commands::Result::Failure)
|
17
17
|
expect(result).to be(false)
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'raises other errors' do
|
21
|
-
expect { users.try { raise ArgumentError, 'test' } }
|
21
|
+
expect { users.try { raise ArgumentError, 'test' } }
|
22
|
+
.to raise_error(ArgumentError, 'test')
|
22
23
|
end
|
23
24
|
end
|
@@ -31,7 +31,6 @@ describe 'Commands / Update' do
|
|
31
31
|
validator UserValidator
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
36
35
|
|
37
36
|
it 'update tuples on successful validation' do
|
@@ -39,7 +38,8 @@ describe 'Commands / Update' do
|
|
39
38
|
update(:all, name: 'Jane').set(email: 'jane.doe@test.com')
|
40
39
|
}
|
41
40
|
|
42
|
-
expect(result)
|
41
|
+
expect(result)
|
42
|
+
.to match_array([{ name: 'Jane', email: 'jane.doe@test.com' }])
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'returns validation object with errors on failed validation' do
|
@@ -54,7 +54,6 @@ describe 'Commands / Update' do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
describe '"result" option' do
|
57
|
-
|
58
57
|
it 'returns a single tuple when set to :one' do
|
59
58
|
setup.commands(:users) do
|
60
59
|
define(:update_one, type: :update) do
|
@@ -69,7 +68,7 @@ describe 'Commands / Update' do
|
|
69
68
|
expect(result.value).to eql(name: 'Jane', email: 'jane.doe@test.com')
|
70
69
|
end
|
71
70
|
|
72
|
-
it 'raises
|
71
|
+
it 'raises when there is more than one tuple and result is set to :one' do
|
73
72
|
setup.commands(:users) do
|
74
73
|
define(:update_one, type: :update) do
|
75
74
|
result :one
|
@@ -90,17 +89,13 @@ describe 'Commands / Update' do
|
|
90
89
|
|
91
90
|
it 'allows only valid result types' do
|
92
91
|
expect {
|
93
|
-
|
94
92
|
setup.commands(:users) do
|
95
93
|
define(:create_one, type: :create) do
|
96
94
|
result :invalid_type
|
97
95
|
end
|
98
96
|
end
|
99
97
|
setup.finalize
|
100
|
-
|
101
98
|
}.to raise_error(ROM::InvalidOptionError)
|
102
99
|
end
|
103
|
-
|
104
100
|
end
|
105
|
-
|
106
101
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Mappers / deeply embedded tuples' do
|
4
|
+
let(:setup) { ROM.setup('memory://test') }
|
5
|
+
let(:rom) { setup.finalize }
|
6
|
+
|
7
|
+
it 'allows mapping embedded tuples' do
|
8
|
+
setup.schema do
|
9
|
+
base_relation(:users) do
|
10
|
+
repository :default
|
11
|
+
attribute 'name'
|
12
|
+
attribute 'tasks'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
setup.relation(:users)
|
17
|
+
|
18
|
+
setup.mappers do
|
19
|
+
define(:users) do
|
20
|
+
model name: 'User'
|
21
|
+
|
22
|
+
attribute :name, from: 'name'
|
23
|
+
|
24
|
+
embedded :tasks, from: 'tasks' do
|
25
|
+
attribute :title, from: 'title'
|
26
|
+
|
27
|
+
embedded :priority, from: 'priority', type: :hash do
|
28
|
+
attribute :value, from: 'value'
|
29
|
+
attribute :desc, from: 'desc'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
rom.schema.users << {
|
36
|
+
'name' => 'Jane',
|
37
|
+
'tasks' => [
|
38
|
+
{ 'title' => 'Task One', 'priority' => { 'value' => 1, 'desc' => 'high' } },
|
39
|
+
{ 'title' => 'Task Two', 'priority' => { 'value' => 3, 'desc' => 'low' } }
|
40
|
+
]
|
41
|
+
}
|
42
|
+
|
43
|
+
jane = rom.read(:users).to_a.first
|
44
|
+
|
45
|
+
expect(jane.name).to eql('Jane')
|
46
|
+
|
47
|
+
expect(jane.tasks).to eql([
|
48
|
+
{ title: 'Task One', priority: { value: 1, desc: 'high' } },
|
49
|
+
{ title: 'Task Two', priority: { value: 3, desc: 'low' } }
|
50
|
+
])
|
51
|
+
end
|
52
|
+
end
|
@@ -101,125 +101,9 @@ describe 'Mapper definition DSL' do
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
describe 'grouped relation mapper' do
|
105
|
-
before do
|
106
|
-
setup.relation(:tasks)
|
107
|
-
|
108
|
-
setup.relation(:users) do
|
109
|
-
include ROM::RA
|
110
|
-
|
111
|
-
def with_tasks
|
112
|
-
join(tasks)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
setup.mappers do
|
117
|
-
define(:users) do
|
118
|
-
model name: 'User'
|
119
|
-
|
120
|
-
attribute :name
|
121
|
-
attribute :email
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'allows defining grouped attributes via options hash' do
|
127
|
-
setup.mappers do
|
128
|
-
define(:with_tasks, parent: :users) do
|
129
|
-
model name: 'UserWithTasks'
|
130
|
-
|
131
|
-
attribute :name
|
132
|
-
attribute :email
|
133
|
-
|
134
|
-
group tasks: [:title, :priority]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
rom = setup.finalize
|
139
|
-
|
140
|
-
UserWithTasks.send(:include, Equalizer.new(:name, :email, :tasks))
|
141
|
-
|
142
|
-
jane = rom.read(:users).with_tasks.to_a.last
|
143
|
-
|
144
|
-
expect(jane).to eql(
|
145
|
-
UserWithTasks.new(
|
146
|
-
name: 'Jane',
|
147
|
-
email: 'jane@doe.org',
|
148
|
-
tasks: [{ title: 'be cool', priority: 2 }]
|
149
|
-
)
|
150
|
-
)
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'allows defining grouped attributes via block' do
|
154
|
-
setup.mappers do
|
155
|
-
define(:with_tasks, parent: :users) do
|
156
|
-
model name: 'UserWithTasks'
|
157
|
-
|
158
|
-
attribute :name
|
159
|
-
attribute :email
|
160
|
-
|
161
|
-
group :tasks do
|
162
|
-
attribute :title
|
163
|
-
attribute :priority
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
rom = setup.finalize
|
169
|
-
|
170
|
-
UserWithTasks.send(:include, Equalizer.new(:name, :email, :tasks))
|
171
|
-
|
172
|
-
jane = rom.read(:users).with_tasks.to_a.last
|
173
|
-
|
174
|
-
expect(jane).to eql(
|
175
|
-
UserWithTasks.new(
|
176
|
-
name: 'Jane',
|
177
|
-
email: 'jane@doe.org',
|
178
|
-
tasks: [{ title: 'be cool', priority: 2 }]
|
179
|
-
)
|
180
|
-
)
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'allows defining grouped attributes mapped to a model via block' do
|
184
|
-
setup.mappers do
|
185
|
-
define(:with_tasks, parent: :users) do
|
186
|
-
model name: 'UserWithTasks'
|
187
|
-
|
188
|
-
attribute :name
|
189
|
-
attribute :email
|
190
|
-
|
191
|
-
group :tasks do
|
192
|
-
model name: 'Task'
|
193
|
-
|
194
|
-
attribute :title
|
195
|
-
attribute :priority
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
rom = setup.finalize
|
201
|
-
|
202
|
-
UserWithTasks.send(:include, Equalizer.new(:name, :email, :tasks))
|
203
|
-
Task.send(:include, Equalizer.new(:title, :priority))
|
204
|
-
|
205
|
-
jane = rom.read(:users).with_tasks.to_a.last
|
206
|
-
|
207
|
-
expect(jane).to eql(
|
208
|
-
UserWithTasks.new(
|
209
|
-
name: 'Jane',
|
210
|
-
email: 'jane@doe.org',
|
211
|
-
tasks: [Task.new(title: 'be cool', priority: 2)]
|
212
|
-
)
|
213
|
-
)
|
214
|
-
end
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
104
|
describe 'wrapped relation mapper' do
|
219
105
|
before do
|
220
106
|
setup.relation(:tasks) do
|
221
|
-
include ROM::RA
|
222
|
-
|
223
107
|
def with_user
|
224
108
|
join(users)
|
225
109
|
end
|
@@ -323,7 +207,5 @@ describe 'Mapper definition DSL' do
|
|
323
207
|
)
|
324
208
|
)
|
325
209
|
end
|
326
|
-
|
327
210
|
end
|
328
|
-
|
329
211
|
end
|