rom 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile +1 -0
- data/README.md +1 -1
- data/lib/rom/command_registry.rb +90 -2
- data/lib/rom/commands/abstract.rb +1 -0
- data/lib/rom/commands/composite.rb +40 -1
- data/lib/rom/env.rb +12 -10
- data/lib/rom/support/options.rb +4 -0
- data/lib/rom/support/registry.rb +6 -2
- data/lib/rom/version.rb +1 -1
- data/rom.gemspec +0 -1
- data/spec/integration/commands/create_spec.rb +74 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/rom/commands_spec.rb +17 -0
- data/spec/unit/rom/env_spec.rb +9 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 865d4e2694bbdadfd473db6464100f268393559d
|
4
|
+
data.tar.gz: b676c75f27251e94c18c654213f27129a6be0651
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e89088463acbd0e5f6f90d599e9d6c8ab2fbc6ef35f9c6f5a12f41c68e5f2a2a471a710ccbc7172568faf750f0cd124abb79a0907b9d4bb9c9d12e3addbd72fa
|
7
|
+
data.tar.gz: f4a6d18309f9874329f7d3ec927ec10ea46bfb19e90d2c73fd5c09009c2735294a01eede5f858531fdeae52748ccc3e2b47c25880ddebae619e41862c02b3837
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## v0.6.1 2015-04-04
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* Ability to auto-map command result via `rom.command(:rel_name).as(:mapper_name)` (solnic)
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
|
9
|
+
* gemspec no longer specifies required_ruby_version so that rom can be installed on jruby (solnic)
|
10
|
+
* Obsolete `Env#readers` was removed (splattael)
|
11
|
+
|
12
|
+
[Compare v0.6.0...v0.6.1](https://github.com/rom-rb/rom/compare/v0.6.0...v0.6.1)
|
13
|
+
|
1
14
|
## v0.6.0 2015-03-22
|
2
15
|
|
3
16
|
### Added
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/lib/rom/command_registry.rb
CHANGED
@@ -1,11 +1,33 @@
|
|
1
1
|
require 'rom/commands/result'
|
2
2
|
|
3
3
|
module ROM
|
4
|
-
#
|
4
|
+
# Specialized registry class for commands
|
5
5
|
#
|
6
6
|
# @api public
|
7
|
-
class CommandRegistry
|
7
|
+
class CommandRegistry
|
8
8
|
include Commands
|
9
|
+
include Options
|
10
|
+
|
11
|
+
# Internal command registry
|
12
|
+
#
|
13
|
+
# @return [Registry]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
attr_reader :registry
|
17
|
+
|
18
|
+
option :mappers, reader: true
|
19
|
+
option :mapper, reader: true
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
def initialize(elements, options = {})
|
23
|
+
super
|
24
|
+
@registry =
|
25
|
+
if elements.is_a?(Registry)
|
26
|
+
elements
|
27
|
+
else
|
28
|
+
Registry.new(elements, self.class.name)
|
29
|
+
end
|
30
|
+
end
|
9
31
|
|
10
32
|
# Try to execute a command in a block
|
11
33
|
#
|
@@ -31,5 +53,71 @@ module ROM
|
|
31
53
|
rescue CommandError => e
|
32
54
|
Result::Failure.new(e)
|
33
55
|
end
|
56
|
+
|
57
|
+
# Return a command from the registry
|
58
|
+
#
|
59
|
+
# If mapper is set command will be turned into a composite command with
|
60
|
+
# auto-mapping
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
# create_user = rom.command(:users)[:create]
|
64
|
+
# create_user[name: 'Jane']
|
65
|
+
#
|
66
|
+
# # with mapping, assuming :entity mapper is registered for :users relation
|
67
|
+
# create_user = rom.command(:users).as(:entity)[:create]
|
68
|
+
# create_user[name: 'Jane'] # => result is send through :entity mapper
|
69
|
+
#
|
70
|
+
# @param [Symbol] name The name of a registered command
|
71
|
+
#
|
72
|
+
# @return [Command,Command::Composite]
|
73
|
+
#
|
74
|
+
# @api public
|
75
|
+
def [](name)
|
76
|
+
command = registry[name]
|
77
|
+
mapper = options[:mapper]
|
78
|
+
|
79
|
+
if mapper
|
80
|
+
command.curry >> mapper
|
81
|
+
else
|
82
|
+
command
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Specify a mapper that should be used for commands from this registry
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# entity_commands = rom.command(:users).as(:entity)
|
90
|
+
#
|
91
|
+
#
|
92
|
+
# @param [Symbol] mapper_name The name of a registered mapper
|
93
|
+
#
|
94
|
+
# @return [CommandRegistry]
|
95
|
+
#
|
96
|
+
# @api public
|
97
|
+
def as(mapper_name)
|
98
|
+
with(mapper: mappers[mapper_name])
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return new instance of this registry with updated options
|
102
|
+
#
|
103
|
+
# @return [CommandRegistry]
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
def with(new_options)
|
107
|
+
self.class.new(registry, options.merge(new_options))
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# Allow retrieving commands using dot-notation
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
def method_missing(name, *)
|
116
|
+
if registry.key?(name)
|
117
|
+
self[name]
|
118
|
+
else
|
119
|
+
super
|
120
|
+
end
|
121
|
+
end
|
34
122
|
end
|
35
123
|
end
|
@@ -29,8 +29,19 @@ module ROM
|
|
29
29
|
#
|
30
30
|
# @api public
|
31
31
|
def call(*args)
|
32
|
-
|
32
|
+
response = left.call(*args)
|
33
|
+
|
34
|
+
if result == :one
|
35
|
+
if right.is_a?(Command) || right.is_a?(Commands::Composite)
|
36
|
+
right.call([response].first)
|
37
|
+
else
|
38
|
+
right.call([response]).first
|
39
|
+
end
|
40
|
+
else
|
41
|
+
right.call(response)
|
42
|
+
end
|
33
43
|
end
|
44
|
+
alias_method :[], :call
|
34
45
|
|
35
46
|
# Compose another composite command from self and other
|
36
47
|
#
|
@@ -42,6 +53,34 @@ module ROM
|
|
42
53
|
def >>(other)
|
43
54
|
self.class.new(self, other)
|
44
55
|
end
|
56
|
+
|
57
|
+
# @api private
|
58
|
+
def result
|
59
|
+
left.result
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api private
|
63
|
+
def respond_to_missing?(name, include_private = false)
|
64
|
+
left.respond_to?(name) || super
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Allow calling methods on the left side object
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
def method_missing(name, *args, &block)
|
73
|
+
if left.respond_to?(name)
|
74
|
+
response = left.__send__(name, *args, &block)
|
75
|
+
if response.is_a?(left.class)
|
76
|
+
self.class.new(response, right)
|
77
|
+
else
|
78
|
+
response
|
79
|
+
end
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
45
84
|
end
|
46
85
|
end
|
47
86
|
end
|
data/lib/rom/env.rb
CHANGED
@@ -17,11 +17,6 @@ module ROM
|
|
17
17
|
# @api public
|
18
18
|
attr_reader :relations
|
19
19
|
|
20
|
-
# @return [ReaderRegistry] reader registry
|
21
|
-
#
|
22
|
-
# @api public
|
23
|
-
attr_reader :readers
|
24
|
-
|
25
20
|
# @return [Registry] command registry
|
26
21
|
#
|
27
22
|
# @api public
|
@@ -33,12 +28,11 @@ module ROM
|
|
33
28
|
attr_reader :mappers
|
34
29
|
|
35
30
|
# @api private
|
36
|
-
def initialize(repositories, relations, mappers, commands
|
31
|
+
def initialize(repositories, relations, mappers, commands)
|
37
32
|
@repositories = repositories
|
38
33
|
@relations = relations
|
39
34
|
@mappers = mappers
|
40
35
|
@commands = commands
|
41
|
-
@readers = readers
|
42
36
|
freeze
|
43
37
|
end
|
44
38
|
|
@@ -69,7 +63,7 @@ module ROM
|
|
69
63
|
relations[name]
|
70
64
|
end
|
71
65
|
|
72
|
-
if mappers.
|
66
|
+
if mappers.key?(name)
|
73
67
|
relation.to_lazy(mappers: mappers[name])
|
74
68
|
else
|
75
69
|
relation.to_lazy
|
@@ -92,7 +86,7 @@ module ROM
|
|
92
86
|
#
|
93
87
|
# @api public
|
94
88
|
def read(name, &block)
|
95
|
-
warn <<-MSG
|
89
|
+
warn <<-MSG.gsub(/^\s+/, '')
|
96
90
|
#{self.class}#read is deprecated.
|
97
91
|
Please use `#{self.class}#relation(#{name.inspect})` instead.
|
98
92
|
For mapping append `.map_with(:your_mapper_name)`
|
@@ -105,11 +99,19 @@ module ROM
|
|
105
99
|
#
|
106
100
|
# @example
|
107
101
|
#
|
102
|
+
# # plain command returning tuples
|
108
103
|
# rom.command(:users).create
|
109
104
|
#
|
105
|
+
# # allow auto-mapping using registered mappers
|
106
|
+
# rom.command(:users).as(:entity)
|
107
|
+
#
|
110
108
|
# @api public
|
111
109
|
def command(name)
|
112
|
-
|
110
|
+
if mappers.key?(name)
|
111
|
+
commands[name].with(mappers: mappers[name])
|
112
|
+
else
|
113
|
+
commands[name]
|
114
|
+
end
|
113
115
|
end
|
114
116
|
end
|
115
117
|
end
|
data/lib/rom/support/options.rb
CHANGED
data/lib/rom/support/registry.rb
CHANGED
@@ -12,9 +12,9 @@ module ROM
|
|
12
12
|
|
13
13
|
attr_reader :elements, :name
|
14
14
|
|
15
|
-
def initialize(elements = {})
|
15
|
+
def initialize(elements = {}, name = self.class.name)
|
16
16
|
@elements = elements
|
17
|
-
@name =
|
17
|
+
@name = name
|
18
18
|
end
|
19
19
|
|
20
20
|
def each(&block)
|
@@ -22,6 +22,10 @@ module ROM
|
|
22
22
|
elements.each { |element| yield(element) }
|
23
23
|
end
|
24
24
|
|
25
|
+
def key?(name)
|
26
|
+
elements.key?(name)
|
27
|
+
end
|
28
|
+
|
25
29
|
def [](key)
|
26
30
|
elements.fetch(key) { raise ElementNotFoundError.new(key, name) }
|
27
31
|
end
|
data/lib/rom/version.rb
CHANGED
data/rom.gemspec
CHANGED
@@ -14,7 +14,6 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.files = `git ls-files`.split("\n").reject { |name| name.include?('benchmarks') }
|
15
15
|
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
16
16
|
gem.license = 'MIT'
|
17
|
-
gem.required_ruby_version = '~> 2.0'
|
18
17
|
|
19
18
|
gem.add_runtime_dependency 'transproc', '~> 0.1', '>= 0.1.2'
|
20
19
|
gem.add_runtime_dependency 'equalizer', '~> 0.0', '>= 0.0.9'
|
@@ -35,9 +35,33 @@ describe 'Commands / Create' do
|
|
35
35
|
result :one
|
36
36
|
|
37
37
|
def execute(user, task)
|
38
|
-
super(task.merge(name: user[:name]))
|
38
|
+
super(task.merge(name: user.to_h[:name]))
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
Test::User = Class.new do
|
43
|
+
include Anima.new(:name, :email)
|
44
|
+
end
|
45
|
+
|
46
|
+
Test::Task = Class.new do
|
47
|
+
include Anima.new(:name, :title)
|
48
|
+
end
|
49
|
+
|
50
|
+
class Test::UserMapper < ROM::Mapper
|
51
|
+
relation :users
|
52
|
+
register_as :entity
|
53
|
+
model Test::User
|
54
|
+
attribute :name
|
55
|
+
attribute :email
|
56
|
+
end
|
57
|
+
|
58
|
+
class Test::TaskMapper < ROM::Mapper
|
59
|
+
relation :tasks
|
60
|
+
register_as :entity
|
61
|
+
model Test::Task
|
62
|
+
attribute :name
|
63
|
+
attribute :title
|
64
|
+
end
|
41
65
|
end
|
42
66
|
|
43
67
|
it 'inserts user on successful validation' do
|
@@ -94,4 +118,53 @@ describe 'Commands / Create' do
|
|
94
118
|
}.to raise_error(ROM::InvalidOptionValueError)
|
95
119
|
end
|
96
120
|
end
|
121
|
+
|
122
|
+
describe 'sending result through a mapper' do
|
123
|
+
let(:attributes) do
|
124
|
+
{ name: 'Jane', email: 'jane@doe.org' }
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'uses registered mapper to process the result for :one result' do
|
128
|
+
command = rom.command(:users).as(:entity).create
|
129
|
+
result = command[attributes]
|
130
|
+
|
131
|
+
expect(result).to eql(Test::User.new(attributes))
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'with two composed commands respects the :result option' do
|
135
|
+
mapper_input = nil
|
136
|
+
|
137
|
+
mapper = proc do |tuples|
|
138
|
+
mapper_input = tuples
|
139
|
+
end
|
140
|
+
|
141
|
+
left = rom.command(:users).as(:entity).create.with(
|
142
|
+
name: 'Jane', email: 'jane@doe.org'
|
143
|
+
)
|
144
|
+
|
145
|
+
right = rom.command(:tasks).as(:entity).create.with(
|
146
|
+
title: 'Jane task'
|
147
|
+
)
|
148
|
+
|
149
|
+
command = left >> right >> mapper
|
150
|
+
|
151
|
+
result = command.call
|
152
|
+
|
153
|
+
task = Test::Task.new(name: 'Jane', title: 'Jane task')
|
154
|
+
|
155
|
+
expect(mapper_input).to eql([task])
|
156
|
+
expect(result).to eql(task)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'uses registered mapper to process the result for :many results' do
|
160
|
+
setup.commands(:users) do
|
161
|
+
define(:create_many, type: :create)
|
162
|
+
end
|
163
|
+
|
164
|
+
command = rom.command(:users).as(:entity).create_many
|
165
|
+
result = command[attributes]
|
166
|
+
|
167
|
+
expect(result).to eql([Test::User.new(attributes)])
|
168
|
+
end
|
169
|
+
end
|
97
170
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -160,6 +160,23 @@ describe 'Commands' do
|
|
160
160
|
expect(result).to eql(task_tuple)
|
161
161
|
expect(logs).to include(task_tuple)
|
162
162
|
end
|
163
|
+
|
164
|
+
it 'forwards methods to the left' do
|
165
|
+
user_input = { name: 'Jane' }
|
166
|
+
user_tuple = { user_id: 1, name: 'Jane' }
|
167
|
+
|
168
|
+
create_user = Class.new(ROM::Commands::Create) {
|
169
|
+
def execute(user_input)
|
170
|
+
relation.insert(user_input)
|
171
|
+
end
|
172
|
+
}.build(users)
|
173
|
+
|
174
|
+
command = create_user >> proc {}
|
175
|
+
|
176
|
+
expect(users).to receive(:insert).with(user_input).and_return(user_tuple)
|
177
|
+
|
178
|
+
command.with(user_input).call
|
179
|
+
end
|
163
180
|
end
|
164
181
|
|
165
182
|
describe 'access to exposed relations' do
|
data/spec/unit/rom/env_spec.rb
CHANGED
@@ -44,6 +44,15 @@ describe ROM::Env do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
describe '#read' do
|
48
|
+
it 'returns loaded relation and display a deprecation warning' do
|
49
|
+
expect {
|
50
|
+
result = rom.read(:users) { |r| r.by_name('Jane') }.as(:name_list)
|
51
|
+
expect(result.call).to match_array([{ name: 'Jane' }])
|
52
|
+
}.to output(/^ROM::Env#read is deprecated/).to_stderr
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
47
56
|
describe '#mappers' do
|
48
57
|
it 'returns mappers for all relations' do
|
49
58
|
expect(rom.mappers.users[:name_list]).to_not be(nil)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: transproc
|
@@ -248,9 +248,9 @@ require_paths:
|
|
248
248
|
- lib
|
249
249
|
required_ruby_version: !ruby/object:Gem::Requirement
|
250
250
|
requirements:
|
251
|
-
- - "
|
251
|
+
- - ">="
|
252
252
|
- !ruby/object:Gem::Version
|
253
|
-
version: '
|
253
|
+
version: '0'
|
254
254
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
255
255
|
requirements:
|
256
256
|
- - ">="
|