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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26bc406252dfc7f8839f49ca5ee2a4a85cb1961db82c0a0a24928e964010ec17
4
- data.tar.gz: b1412660d447cba69a18ffa3a290942de9339751abf2aebbd737b8326b7d7b57
3
+ metadata.gz: 43fa8164083ceda9dca36dc6584da4bf3ac511e67d0f7a2232468ae841f8bd56
4
+ data.tar.gz: 1ed5b56c2524f9f73048a8f9f79c2ab4515bafe0749a60122b92841224b5194c
5
5
  SHA512:
6
- metadata.gz: 02b54f2d308bbac395167a086aecbcca66bd2780a9a13871243ca150789b36d4f0717aec967b3fb5201e07e9ee9324b3a3ecfde203c2dd8bd3c15bc8d0b2ae22
7
- data.tar.gz: ce8dda0f8c1a366dc311db0d32e7526d9fbf7bef45d23a3c77c49b67f591c06084f8a6a9ab1aa43063c002f42aaf1f1eecb93be10968b4803971cc6bc142a418
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
- MAINTAINER Ryan Schlesinger <ryan@outstand.com>
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
@@ -1,3 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+ gem 'pry-byebug'
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::Errors, method: :include },
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, **args)
12
- add_error(message: message, **args)
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, **args)
21
+ def add_error(message: nil, errors: nil)
22
22
  if message.nil?
23
- add_errors(errors: [**args])
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
- self.errors += messages
31
- self.errors += errors
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.map do |error|
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
@@ -1,28 +1,102 @@
1
+ require 'sycamore'
1
2
  require 'forwardable'
2
-
3
3
  module Metaractor
4
- class Error < StandardError; end
5
- class InvalidError < Error; end
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
- module Errors
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 fail_with_errors!(*args)
13
- context.fail_with_errors!(*args)
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 add_error(*args)
17
- context.add_error(*args)
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 add_errors(*args)
21
- context.add_errors(*args)
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 error_messages
25
- context.error_messages
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
@@ -4,7 +4,7 @@ module Metaractor
4
4
  return if context.equal?(self)
5
5
 
6
6
  invalidate! if context.invalid?
7
- add_errors(messages: context.errors)
7
+ add_errors(errors: context.errors.to_h)
8
8
  @failure = true
9
9
  end
10
10
  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
@@ -3,7 +3,7 @@ module Metaractor
3
3
  def self.included(base)
4
4
  base.extend ClassMethods
5
5
  base.class_eval do
6
- include Metaractor::Errors
6
+ include Metaractor::HandleErrors
7
7
 
8
8
  class << self
9
9
  attr_writer :_required_parameters
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Metaractor
2
- VERSION = "1.2.1"
2
+ VERSION = "2.0.0"
3
3
  end
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', '~> 1.12'
24
- spec.add_development_dependency 'rake', '~> 10.0'
25
- spec.add_development_dependency 'rspec', '~> 3.4'
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: 1.2.1
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-01-24 00:00:00.000000000 Z
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: '1.12'
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: '1.12'
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: '10.0'
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: '10.0'
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.4'
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.4'
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