metaractor 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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