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/adapter/memory.rb
CHANGED
@@ -4,7 +4,6 @@ require 'rom/adapter/memory/commands'
|
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
class Adapter
|
7
|
-
|
8
7
|
class Memory < Adapter
|
9
8
|
attr_accessor :logger
|
10
9
|
|
@@ -28,9 +27,6 @@ module ROM
|
|
28
27
|
def [](name)
|
29
28
|
connection[name]
|
30
29
|
end
|
31
|
-
|
32
|
-
Adapter.register(self)
|
33
30
|
end
|
34
|
-
|
35
31
|
end
|
36
32
|
end
|
@@ -1,41 +1,31 @@
|
|
1
1
|
module ROM
|
2
2
|
class Adapter
|
3
3
|
class Memory < Adapter
|
4
|
-
|
5
4
|
module Commands
|
6
|
-
|
7
5
|
class Create < ROM::Commands::Create
|
8
|
-
|
9
6
|
def execute(tuple)
|
10
7
|
attributes = input[tuple]
|
11
8
|
validator.call(attributes)
|
12
9
|
[relation.insert(attributes.to_h).to_a.last]
|
13
10
|
end
|
14
|
-
|
15
11
|
end
|
16
12
|
|
17
13
|
class Update < ROM::Commands::Update
|
18
|
-
|
19
14
|
def execute(params)
|
20
15
|
attributes = input[params]
|
21
16
|
validator.call(attributes)
|
22
17
|
relation.map { |tuple| tuple.update(attributes.to_h) }
|
23
18
|
end
|
24
|
-
|
25
19
|
end
|
26
20
|
|
27
21
|
class Delete < ROM::Commands::Delete
|
28
|
-
|
29
22
|
def execute
|
30
23
|
tuples = target.to_a
|
31
24
|
tuples.each { |tuple| relation.delete(tuple) }
|
32
25
|
tuples
|
33
26
|
end
|
34
|
-
|
35
27
|
end
|
36
|
-
|
37
28
|
end
|
38
|
-
|
39
29
|
end
|
40
30
|
end
|
41
31
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module ROM
|
2
2
|
class Adapter
|
3
3
|
class Memory < Adapter
|
4
|
-
|
5
4
|
class Dataset
|
6
5
|
include Charlatan.new(:data)
|
7
6
|
|
@@ -22,16 +21,31 @@ module ROM
|
|
22
21
|
data.each(&block)
|
23
22
|
end
|
24
23
|
|
25
|
-
def
|
24
|
+
def join(*args)
|
25
|
+
left, right = args.size > 1 ? args : [self, args.first]
|
26
|
+
|
27
|
+
join_map = left.to_a.each_with_object({}) { |tuple, h|
|
28
|
+
others = right.to_a.find_all { |t| (tuple.to_a & t.to_a).any? }
|
29
|
+
(h[tuple] ||= []).concat(others)
|
30
|
+
}
|
31
|
+
|
32
|
+
tuples = left.map { |tuple|
|
33
|
+
join_map[tuple].map { |other| tuple.merge(other) }
|
34
|
+
}.flatten
|
35
|
+
|
36
|
+
self.class.new(tuples, left.header + right.header)
|
37
|
+
end
|
38
|
+
|
39
|
+
def restrict(criteria = nil)
|
26
40
|
if criteria
|
27
|
-
find_all { |tuple| criteria.all? { |k, v| tuple[k]
|
41
|
+
find_all { |tuple| criteria.all? { |k, v| tuple[k].eql?(v) } }
|
28
42
|
else
|
29
43
|
find_all { |tuple| yield(tuple) }
|
30
44
|
end
|
31
45
|
end
|
32
46
|
|
33
47
|
def project(*names)
|
34
|
-
map { |tuple| tuple.reject { |key
|
48
|
+
map { |tuple| tuple.reject { |key| !names.include?(key) } }
|
35
49
|
end
|
36
50
|
|
37
51
|
def order(*names)
|
@@ -47,9 +61,7 @@ module ROM
|
|
47
61
|
data.delete(tuple)
|
48
62
|
self
|
49
63
|
end
|
50
|
-
|
51
64
|
end
|
52
|
-
|
53
65
|
end
|
54
66
|
end
|
55
67
|
end
|
data/lib/rom/command_registry.rb
CHANGED
@@ -1,50 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Result
|
4
|
-
attr_reader :value, :error
|
5
|
-
|
6
|
-
def to_ary
|
7
|
-
raise NotImplementedError
|
8
|
-
end
|
9
|
-
alias_method :to_a, :to_ary
|
10
|
-
|
11
|
-
class Success < Result
|
12
|
-
def initialize(value)
|
13
|
-
@value = value
|
14
|
-
end
|
15
|
-
|
16
|
-
def >(f)
|
17
|
-
f.call(value)
|
18
|
-
end
|
19
|
-
|
20
|
-
def to_ary
|
21
|
-
value
|
22
|
-
end
|
23
|
-
alias_method :to_a, :to_ary
|
24
|
-
end
|
25
|
-
|
26
|
-
class Failure < Result
|
27
|
-
def initialize(error)
|
28
|
-
@error = error
|
29
|
-
end
|
30
|
-
|
31
|
-
def >(f)
|
32
|
-
self
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_ary
|
36
|
-
error
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
1
|
+
require 'rom/commands/result'
|
40
2
|
|
3
|
+
module ROM
|
4
|
+
# Command registry exposes "try" interface for executing commands
|
5
|
+
#
|
6
|
+
# @public
|
41
7
|
class CommandRegistry < Registry
|
42
|
-
|
43
8
|
class Evaluator
|
44
9
|
include Concord.new(:registry)
|
45
10
|
|
46
11
|
private
|
47
12
|
|
13
|
+
# Call a command when method is matching command name
|
14
|
+
#
|
15
|
+
# TODO: this will be replaced by explicit definition of methods for all
|
16
|
+
# registered commands
|
17
|
+
#
|
18
|
+
# @api public
|
48
19
|
def method_missing(name, *args, &block)
|
49
20
|
command = registry[name]
|
50
21
|
|
@@ -58,11 +29,21 @@ module ROM
|
|
58
29
|
end
|
59
30
|
end
|
60
31
|
|
32
|
+
# Try to execute a command in a block
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
#
|
36
|
+
# rom.command(:users).try { create(name: 'Jane') }
|
37
|
+
# rom.command(:users).try { update(:by_id, 1).set(name: 'Jane Doe') }
|
38
|
+
# rom.command(:users).try { delete(:by_id, 1) }
|
39
|
+
#
|
40
|
+
# @return [Commands::Result]
|
41
|
+
#
|
42
|
+
# @api public
|
61
43
|
def try(&f)
|
62
|
-
Result::Success.new(Evaluator.new(self).instance_exec(&f))
|
44
|
+
Commands::Result::Success.new(Evaluator.new(self).instance_exec(&f))
|
63
45
|
rescue CommandError => e
|
64
|
-
Result::Failure.new(e)
|
46
|
+
Commands::Result::Failure.new(e)
|
65
47
|
end
|
66
48
|
end
|
67
|
-
|
68
49
|
end
|
data/lib/rom/commands.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
|
-
|
4
3
|
class AbstractCommand
|
5
4
|
VALID_RESULTS = [:one, :many].freeze
|
6
5
|
|
@@ -13,7 +12,7 @@ module ROM
|
|
13
12
|
|
14
13
|
@result = options[:result] || :many
|
15
14
|
|
16
|
-
|
15
|
+
unless VALID_RESULTS.include?(result)
|
17
16
|
raise InvalidOptionError.new(:result, VALID_RESULTS)
|
18
17
|
end
|
19
18
|
end
|
@@ -34,7 +33,8 @@ module ROM
|
|
34
33
|
# Target relation on which the command will operate
|
35
34
|
#
|
36
35
|
# By default this is set to the relation that's passed to the constructor.
|
37
|
-
# Specialized commands like Delete may set the target to a different
|
36
|
+
# Specialized commands like Delete may set the target to a different
|
37
|
+
# relation.
|
38
38
|
#
|
39
39
|
# @return [Relation]
|
40
40
|
#
|
@@ -43,7 +43,8 @@ module ROM
|
|
43
43
|
relation
|
44
44
|
end
|
45
45
|
|
46
|
-
# Assert that tuple count in the target relation corresponds to :result
|
46
|
+
# Assert that tuple count in the target relation corresponds to :result
|
47
|
+
# setting
|
47
48
|
#
|
48
49
|
# @raises TupleCountMismatchError
|
49
50
|
#
|
@@ -53,9 +54,7 @@ module ROM
|
|
53
54
|
raise TupleCountMismatchError, "#{inspect} expects one tuple"
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
57
|
end
|
58
|
-
|
59
58
|
end
|
60
59
|
end
|
61
60
|
|
data/lib/rom/commands/create.rb
CHANGED
@@ -2,7 +2,6 @@ require 'rom/commands/with_options'
|
|
2
2
|
|
3
3
|
module ROM
|
4
4
|
module Commands
|
5
|
-
|
6
5
|
# Create command
|
7
6
|
#
|
8
7
|
# This command inserts a new tuple into a relation
|
@@ -18,11 +17,12 @@ module ROM
|
|
18
17
|
# @return [Array] an array with inserted tuples
|
19
18
|
#
|
20
19
|
# @api private
|
21
|
-
def execute(
|
22
|
-
raise
|
20
|
+
def execute(_tuple)
|
21
|
+
raise(
|
22
|
+
NotImplementedError,
|
23
|
+
"#{self.class}##{__method__} must be implemented"
|
24
|
+
)
|
23
25
|
end
|
24
|
-
|
25
26
|
end
|
26
|
-
|
27
27
|
end
|
28
28
|
end
|
data/lib/rom/commands/delete.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
|
-
|
4
3
|
# Delete command
|
5
4
|
#
|
6
5
|
# This command removes tuples from its target relation
|
@@ -28,17 +27,20 @@ module ROM
|
|
28
27
|
#
|
29
28
|
# @api private
|
30
29
|
def execute
|
31
|
-
raise
|
30
|
+
raise(
|
31
|
+
NotImplementedError,
|
32
|
+
"#{self.class}##{__method__} must be implemented"
|
33
|
+
)
|
32
34
|
end
|
33
35
|
|
34
|
-
#
|
36
|
+
# Create a new delete command scoped to specific relation and execute it
|
35
37
|
#
|
36
38
|
# @api private
|
37
39
|
def new(*args, &block)
|
38
|
-
|
40
|
+
new_options = options.merge(target: relation.public_send(*args, &block))
|
41
|
+
command = self.class.new(relation, new_options)
|
42
|
+
command.call
|
39
43
|
end
|
40
|
-
|
41
44
|
end
|
42
|
-
|
43
45
|
end
|
44
46
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ROM
|
2
|
+
module Commands
|
3
|
+
# Abstract result class for success and error results
|
4
|
+
#
|
5
|
+
# @public
|
6
|
+
class Result
|
7
|
+
# Return command execution result
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
attr_reader :value
|
11
|
+
|
12
|
+
# Return potential command execution result error
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
attr_reader :error
|
16
|
+
|
17
|
+
# Coerce result to an array
|
18
|
+
#
|
19
|
+
# @abstract
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def to_ary
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
alias_method :to_a, :to_ary
|
26
|
+
|
27
|
+
# Success result has a value and no error
|
28
|
+
#
|
29
|
+
# @public
|
30
|
+
class Success < Result
|
31
|
+
# @api private
|
32
|
+
def initialize(value)
|
33
|
+
@value = value
|
34
|
+
end
|
35
|
+
|
36
|
+
# Call next command on continuation
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
def >(other)
|
40
|
+
other.call(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return the value
|
44
|
+
#
|
45
|
+
# @return [Array]
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
def to_ary
|
49
|
+
value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Failure result has an error and no value
|
54
|
+
#
|
55
|
+
# @public
|
56
|
+
class Failure < Result
|
57
|
+
# @api private
|
58
|
+
def initialize(error)
|
59
|
+
@error = error
|
60
|
+
end
|
61
|
+
|
62
|
+
# Do not call next command on continuation
|
63
|
+
#
|
64
|
+
# @return [self]
|
65
|
+
#
|
66
|
+
# @api public
|
67
|
+
def >(_other)
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return the error
|
72
|
+
#
|
73
|
+
# @return [Array<CommandError>]
|
74
|
+
#
|
75
|
+
# @api public
|
76
|
+
def to_ary
|
77
|
+
error
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/rom/commands/update.rb
CHANGED
@@ -2,7 +2,6 @@ require 'rom/commands/with_options'
|
|
2
2
|
|
3
3
|
module ROM
|
4
4
|
module Commands
|
5
|
-
|
6
5
|
# Update command
|
7
6
|
#
|
8
7
|
# This command updates all tuples in its relation with new attributes
|
@@ -26,8 +25,11 @@ module ROM
|
|
26
25
|
# @abstract
|
27
26
|
#
|
28
27
|
# @api private
|
29
|
-
def execute(
|
30
|
-
raise
|
28
|
+
def execute(_params)
|
29
|
+
raise(
|
30
|
+
NotImplementedError,
|
31
|
+
"#{self.class}##{__method__} must be implemented"
|
32
|
+
)
|
31
33
|
end
|
32
34
|
|
33
35
|
# Return new update command with new relation
|
@@ -37,6 +39,5 @@ module ROM
|
|
37
39
|
self.class.new(relation.public_send(*args, &block), options)
|
38
40
|
end
|
39
41
|
end
|
40
|
-
|
41
42
|
end
|
42
43
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module ROM
|
2
2
|
module Commands
|
3
|
-
|
4
3
|
# Common behavior for Create and Update commands
|
5
4
|
#
|
6
5
|
# TODO: find a better name for this module
|
@@ -11,11 +10,9 @@ module ROM
|
|
11
10
|
def initialize(relation, options)
|
12
11
|
super
|
13
12
|
|
14
|
-
@validator = options[:validator] ||
|
13
|
+
@validator = options[:validator] || proc {}
|
15
14
|
@input = options[:input] || Hash
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
|
-
|
20
17
|
end
|
21
18
|
end
|