metaractor 1.2.1 → 2.0.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/Dockerfile +4 -1
- data/Gemfile +1 -0
- data/lib/metaractor.rb +2 -1
- data/lib/metaractor/context_errors.rb +13 -20
- data/lib/metaractor/errors.rb +88 -14
- data/lib/metaractor/fail_from_context.rb +1 -1
- data/lib/metaractor/handle_errors.rb +26 -0
- data/lib/metaractor/parameters.rb +1 -1
- data/lib/metaractor/spec.rb +74 -0
- data/lib/metaractor/version.rb +1 -1
- data/metaractor.gemspec +4 -3
- metadata +24 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43fa8164083ceda9dca36dc6584da4bf3ac511e67d0f7a2232468ae841f8bd56
|
4
|
+
data.tar.gz: 1ed5b56c2524f9f73048a8f9f79c2ab4515bafe0749a60122b92841224b5194c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 535d587dde182fd7c298f050eefb6a560a35f27ffba8e90afd117a0395f760374b88794c09e2cd84821ba760b26ee0322bd1fd95d8d9b0b2c22dceac8b7cac14
|
7
|
+
data.tar.gz: 8571061ff4a4fcd37d3592a82273db4bf308f394b92bb7f36b2241fbbb07cbca4c2e1b05882af339c4a99891efc0688e23d4f7643e12842e200e18379ac78ec4
|
data/Dockerfile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
FROM ruby:2.6.5-alpine
|
2
|
-
|
2
|
+
LABEL maintainer="Ryan Schlesinger <ryan@outstand.com>"
|
3
3
|
|
4
4
|
RUN addgroup -g 1000 -S metaractor && \
|
5
5
|
adduser -u 1000 -S -s /bin/ash -G metaractor metaractor && \
|
@@ -11,6 +11,9 @@ RUN addgroup -g 1000 -S metaractor && \
|
|
11
11
|
git \
|
12
12
|
openssh
|
13
13
|
|
14
|
+
ENV BUNDLER_VERSION 2.1.4
|
15
|
+
RUN gem install bundler -v ${BUNDLER_VERSION} -i /usr/local/lib/ruby/gems/$(ls /usr/local/lib/ruby/gems) --force
|
16
|
+
|
14
17
|
WORKDIR /metaractor
|
15
18
|
RUN chown -R metaractor:metaractor /metaractor
|
16
19
|
USER metaractor
|
data/Gemfile
CHANGED
data/lib/metaractor.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'metaractor/version'
|
2
2
|
require 'interactor'
|
3
3
|
require 'metaractor/errors'
|
4
|
+
require 'metaractor/handle_errors'
|
4
5
|
require 'metaractor/context_errors'
|
5
6
|
require 'metaractor/parameters'
|
6
7
|
require 'metaractor/run_with_context'
|
@@ -38,7 +39,7 @@ module Metaractor
|
|
38
39
|
|
39
40
|
def self.default_modules
|
40
41
|
[
|
41
|
-
{ module: Metaractor::
|
42
|
+
{ module: Metaractor::HandleErrors, method: :include },
|
42
43
|
{ module: Metaractor::Parameters, method: :include },
|
43
44
|
{ module: Metaractor::RunWithContext, method: :include },
|
44
45
|
{ module: Metaractor::ChainFailures, method: :include }
|
@@ -2,47 +2,40 @@ module Metaractor
|
|
2
2
|
module ContextErrors
|
3
3
|
def errors
|
4
4
|
if super.nil?
|
5
|
-
self.errors =
|
5
|
+
self.errors = Metaractor::Errors.new
|
6
6
|
end
|
7
7
|
|
8
8
|
super
|
9
9
|
end
|
10
10
|
|
11
|
-
def fail_with_error!(message: nil,
|
12
|
-
add_error(message: message,
|
11
|
+
def fail_with_error!(message: nil, errors: nil)
|
12
|
+
add_error(message: message, errors: errors)
|
13
13
|
fail!
|
14
14
|
end
|
15
15
|
|
16
|
-
def fail_with_errors!(messages: [], errors:
|
16
|
+
def fail_with_errors!(messages: [], errors: {})
|
17
17
|
add_errors(messages: messages, errors: errors)
|
18
18
|
fail!
|
19
19
|
end
|
20
20
|
|
21
|
-
def add_error(message: nil,
|
21
|
+
def add_error(message: nil, errors: nil)
|
22
22
|
if message.nil?
|
23
|
-
add_errors(errors:
|
23
|
+
add_errors(errors: errors)
|
24
24
|
else
|
25
25
|
add_errors(messages: Array(message))
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def add_errors(messages: [], errors:
|
30
|
-
|
31
|
-
|
29
|
+
def add_errors(messages: [], errors: {})
|
30
|
+
if !messages.empty?
|
31
|
+
self.errors.add(errors: { base: messages })
|
32
|
+
else
|
33
|
+
self.errors.add(errors: errors)
|
34
|
+
end
|
32
35
|
end
|
33
36
|
|
34
37
|
def error_messages
|
35
|
-
errors.
|
36
|
-
if error.respond_to?(:has_key?) && error.has_key?(:title)
|
37
|
-
if error[:source] != nil
|
38
|
-
"#{error[:source]}: #{error[:title]}"
|
39
|
-
else
|
40
|
-
error[:title].to_s
|
41
|
-
end
|
42
|
-
else
|
43
|
-
error.to_s
|
44
|
-
end
|
45
|
-
end.join("\n")
|
38
|
+
errors.full_messages
|
46
39
|
end
|
47
40
|
end
|
48
41
|
end
|
data/lib/metaractor/errors.rb
CHANGED
@@ -1,28 +1,102 @@
|
|
1
|
+
require 'sycamore'
|
1
2
|
require 'forwardable'
|
2
|
-
|
3
3
|
module Metaractor
|
4
|
-
class
|
5
|
-
|
4
|
+
class Errors
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@tree = Sycamore::Tree.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def_delegators :@tree, :to_h, :empty?
|
12
|
+
|
13
|
+
def add(error: {}, errors: {})
|
14
|
+
trees = []
|
15
|
+
[error, errors].each do |h|
|
16
|
+
tree = nil
|
17
|
+
if h.is_a? Metaractor::Errors
|
18
|
+
tree = Sycamore::Tree.from(h.instance_variable_get(:@tree))
|
19
|
+
else
|
20
|
+
tree = Sycamore::Tree.from(h)
|
21
|
+
end
|
22
|
+
|
23
|
+
unless tree.empty?
|
24
|
+
if tree.nodes.any? {|node| tree.strict_leaf?(node) }
|
25
|
+
raise ArgumentError, "Invalid hash!"
|
26
|
+
end
|
27
|
+
trees << tree
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
trees.each do |tree|
|
32
|
+
@tree.add(tree)
|
33
|
+
end
|
34
|
+
@tree.compact
|
35
|
+
end
|
36
|
+
|
37
|
+
def full_messages(tree = @tree)
|
38
|
+
messages = []
|
39
|
+
tree.each_path do |path|
|
40
|
+
messages << message_from_path(path)
|
41
|
+
end
|
6
42
|
|
7
|
-
|
8
|
-
def fail_with_error!(*args)
|
9
|
-
context.fail_with_error!(*args)
|
43
|
+
messages
|
10
44
|
end
|
45
|
+
alias to_a full_messages
|
11
46
|
|
12
|
-
def
|
13
|
-
|
47
|
+
def full_messages_for(*path)
|
48
|
+
child_tree = @tree.fetch_path(path)
|
49
|
+
|
50
|
+
if child_tree.strict_leaves?
|
51
|
+
child_tree = @tree.fetch_path(path[0..-2])
|
52
|
+
end
|
53
|
+
|
54
|
+
full_messages(child_tree)
|
14
55
|
end
|
15
56
|
|
16
|
-
def
|
17
|
-
|
57
|
+
def dig(*path)
|
58
|
+
result = @tree.dig(*path)
|
59
|
+
|
60
|
+
if result.strict_leaves?
|
61
|
+
result.nodes
|
62
|
+
else
|
63
|
+
result.to_h
|
64
|
+
end
|
18
65
|
end
|
66
|
+
alias [] dig
|
19
67
|
|
20
|
-
def
|
21
|
-
|
68
|
+
def include?(*elements)
|
69
|
+
if elements.size == 1 &&
|
70
|
+
elements.first.is_a?(Hash)
|
71
|
+
@tree.include?(*elements)
|
72
|
+
else
|
73
|
+
full_messages.include?(*elements)
|
74
|
+
end
|
22
75
|
end
|
23
76
|
|
24
|
-
def
|
25
|
-
|
77
|
+
def slice(*paths)
|
78
|
+
new_tree = Sycamore::Tree.new
|
79
|
+
|
80
|
+
paths.each do |path|
|
81
|
+
if @tree.include_path?(path)
|
82
|
+
new_tree[path] = @tree[path].dup
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
new_tree.to_h
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def message_from_path(path)
|
92
|
+
path_elements = []
|
93
|
+
path.parent&.each_node do |node|
|
94
|
+
unless node == :base
|
95
|
+
path_elements << node.to_s
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
"#{path_elements.join('.')} #{path.node.to_s}".lstrip
|
26
100
|
end
|
27
101
|
end
|
28
102
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Metaractor
|
2
|
+
class Error < StandardError; end
|
3
|
+
class InvalidError < Error; end
|
4
|
+
|
5
|
+
module HandleErrors
|
6
|
+
def fail_with_error!(*args)
|
7
|
+
context.fail_with_error!(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def fail_with_errors!(*args)
|
11
|
+
context.fail_with_errors!(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_error(*args)
|
15
|
+
context.add_error(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_errors(*args)
|
19
|
+
context.add_errors(*args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def error_messages
|
23
|
+
context.error_messages
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'metaractor'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Metaractor
|
5
|
+
module Spec
|
6
|
+
module Helpers
|
7
|
+
def context_creator(error_message: nil, error_messages: [], errors: [], valid: nil, invalid: nil, success: nil, failure: nil, **attributes)
|
8
|
+
if error_message.present?
|
9
|
+
error_messages << error_message
|
10
|
+
end
|
11
|
+
|
12
|
+
result = Interactor::Context.build(attributes)
|
13
|
+
result.add_errors(messages: error_messages)
|
14
|
+
result.add_errors(errors: errors)
|
15
|
+
|
16
|
+
if (valid != nil && !valid) || (invalid != nil && invalid)
|
17
|
+
result.invalidate!
|
18
|
+
end
|
19
|
+
|
20
|
+
if !result.errors.empty? ||
|
21
|
+
result.invalid? ||
|
22
|
+
(success != nil && !success) ||
|
23
|
+
(failure != nil && failure)
|
24
|
+
result.fail! rescue Interactor::Failure
|
25
|
+
end
|
26
|
+
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Matchers
|
32
|
+
def include_errors(*expected)
|
33
|
+
Metaractor::Spec::Matchers::IncludeErrors.new(*expected)
|
34
|
+
end
|
35
|
+
|
36
|
+
class IncludeErrors
|
37
|
+
extend Forwardable
|
38
|
+
|
39
|
+
def initialize(*expected)
|
40
|
+
@expected = expected
|
41
|
+
@include = RSpec::Matchers::BuiltIn::Include.new(*@expected)
|
42
|
+
end
|
43
|
+
|
44
|
+
def matches?(actual)
|
45
|
+
@actual = actual
|
46
|
+
@include.matches?(full_messages)
|
47
|
+
end
|
48
|
+
|
49
|
+
def does_not_match?(actual)
|
50
|
+
@actual = actual
|
51
|
+
@include.does_not_match?(full_messages)
|
52
|
+
end
|
53
|
+
|
54
|
+
def at_path(*path)
|
55
|
+
@path = path
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def_delegators :@include, :description, :failure_message, :failure_message_when_negated, :diffable?, :actual, :expected
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def full_messages
|
64
|
+
if @path
|
65
|
+
@actual.errors.full_messages_for(*@path)
|
66
|
+
else
|
67
|
+
@actual.errors.full_messages
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
data/lib/metaractor/version.rb
CHANGED
data/metaractor.gemspec
CHANGED
@@ -19,8 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
spec.add_runtime_dependency 'interactor', '~> 3.1'
|
22
|
+
spec.add_runtime_dependency 'sycamore', '~> 0.3'
|
22
23
|
|
23
|
-
spec.add_development_dependency 'bundler', '~>
|
24
|
-
spec.add_development_dependency 'rake', '~>
|
25
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
24
|
+
spec.add_development_dependency 'bundler', '~> 2'
|
25
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.9'
|
26
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metaractor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Schlesinger
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interactor
|
@@ -24,48 +24,62 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sycamore
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.3'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '2'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '2'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '13.0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '13.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rspec
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
75
|
+
version: '3.9'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3.
|
82
|
+
version: '3.9'
|
69
83
|
description:
|
70
84
|
email:
|
71
85
|
- ryan@outstand.com
|
@@ -89,8 +103,10 @@ files:
|
|
89
103
|
- lib/metaractor/context_validity.rb
|
90
104
|
- lib/metaractor/errors.rb
|
91
105
|
- lib/metaractor/fail_from_context.rb
|
106
|
+
- lib/metaractor/handle_errors.rb
|
92
107
|
- lib/metaractor/parameters.rb
|
93
108
|
- lib/metaractor/run_with_context.rb
|
109
|
+
- lib/metaractor/spec.rb
|
94
110
|
- lib/metaractor/version.rb
|
95
111
|
- metaractor.gemspec
|
96
112
|
homepage: https://github.com/outstand/metaractor
|