metaractor 0.5.0 → 1.1.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 +5 -5
- data/Dockerfile +18 -39
- data/README.md +58 -1
- data/docker-compose.yml +24 -0
- data/docker-entrypoint.sh +12 -4
- data/lib/metaractor/chain_failures.rb +16 -0
- data/lib/metaractor/context_errors.rb +35 -0
- data/lib/metaractor/errors.rb +11 -22
- data/lib/metaractor/fail_from_context.rb +13 -0
- data/lib/metaractor/parameters.rb +0 -2
- data/lib/metaractor/version.rb +1 -1
- data/lib/metaractor.rb +5 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 61aa5597f77391b54b18d7a7d31e6b3cef5d00c844702fc3e1ef06c2dc8b0b1d
|
4
|
+
data.tar.gz: 5749efb4aa913aa4e4157e1213abedf689766add06df57544a41ac85aae47b0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c0d070919763827f78dee03c6667022faaf0b1882b65d527c1829f287b3ce7fa33efc91b8b55cb85e0edd1e808917b5d1b2e5d6833a151e33728b40f5df64d8
|
7
|
+
data.tar.gz: a5969b17f7cbe5c2f447e5b43dca00662e6bf8cdf23f96414fb0257d1b4aec4eaf1c02899dbf06947f582739995e015830d06b3857a65d36cfb8c5a260d259d4
|
data/Dockerfile
CHANGED
@@ -1,48 +1,27 @@
|
|
1
|
-
FROM ruby:2.
|
1
|
+
FROM ruby:2.5.1-alpine
|
2
2
|
MAINTAINER Ryan Schlesinger <ryan@outstand.com>
|
3
3
|
|
4
|
-
RUN addgroup metaractor && \
|
5
|
-
adduser -S -G metaractor metaractor
|
4
|
+
RUN addgroup -g 1000 -S metaractor && \
|
5
|
+
adduser -u 1000 -S -s /bin/ash -G metaractor metaractor && \
|
6
|
+
apk add --no-cache \
|
7
|
+
ca-certificates \
|
8
|
+
tini \
|
9
|
+
su-exec \
|
10
|
+
build-base \
|
11
|
+
git \
|
12
|
+
openssh
|
6
13
|
|
7
|
-
|
8
|
-
ENV DUMB_INIT_VERSION 1.0.3
|
9
|
-
|
10
|
-
RUN apk add --no-cache ca-certificates gnupg && \
|
11
|
-
mkdir -p /tmp/build && \
|
12
|
-
cd /tmp/build && \
|
13
|
-
gpg --keyserver pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && \
|
14
|
-
curl -o gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" && \
|
15
|
-
curl -o gosu.asc -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc" && \
|
16
|
-
gpg --verify gosu.asc && \
|
17
|
-
chmod +x gosu && \
|
18
|
-
cp gosu /bin/gosu && \
|
19
|
-
wget https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_amd64 && \
|
20
|
-
wget https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/sha256sums && \
|
21
|
-
grep dumb-init_${DUMB_INIT_VERSION}_amd64$ sha256sums | sha256sum -c && \
|
22
|
-
chmod +x dumb-init_${DUMB_INIT_VERSION}_amd64 && \
|
23
|
-
cp dumb-init_${DUMB_INIT_VERSION}_amd64 /bin/dumb-init && \
|
24
|
-
cd /tmp && \
|
25
|
-
rm -rf /tmp/build && \
|
26
|
-
apk del gnupg && \
|
27
|
-
rm -rf /root/.gnupg
|
28
|
-
|
29
|
-
RUN apk add --no-cache \
|
30
|
-
build-base \
|
31
|
-
git \
|
32
|
-
openssh
|
33
|
-
|
34
|
-
COPY Gemfile metaractor.gemspec /metaractor/
|
35
|
-
COPY lib/metaractor/version.rb /metaractor/lib/metaractor/
|
36
|
-
RUN cd /metaractor \
|
37
|
-
&& bundle install \
|
38
|
-
&& git config --global push.default simple
|
39
|
-
COPY . /metaractor/
|
14
|
+
WORKDIR /metaractor
|
40
15
|
RUN chown -R metaractor:metaractor /metaractor
|
16
|
+
USER metaractor
|
41
17
|
|
42
|
-
|
18
|
+
COPY --chown=metaractor:metaractor Gemfile metaractor.gemspec /metaractor/
|
19
|
+
COPY --chown=metaractor:metaractor lib/metaractor/version.rb /metaractor/lib/metaractor/
|
20
|
+
RUN git config --global push.default simple
|
21
|
+
COPY --chown=metaractor:metaractor . /metaractor/
|
43
22
|
|
23
|
+
USER root
|
44
24
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
45
25
|
|
46
|
-
|
47
|
-
ENTRYPOINT ["/docker-entrypoint.sh"]
|
26
|
+
ENTRYPOINT ["/sbin/tini", "-g", "--", "/docker-entrypoint.sh"]
|
48
27
|
CMD ["rspec", "spec"]
|
data/README.md
CHANGED
@@ -38,10 +38,67 @@ class HighFiveUser
|
|
38
38
|
# private
|
39
39
|
# delegate :user, to: context
|
40
40
|
end
|
41
|
+
|
42
|
+
result = HighFiveUser.call # not passing user or user_id
|
43
|
+
result.failure?
|
44
|
+
# => true
|
45
|
+
result.valid?
|
46
|
+
# => false
|
47
|
+
result.errors
|
48
|
+
# => ["Required parameters: (user_id or user)"]
|
41
49
|
```
|
42
50
|
|
43
51
|
See Interactor's [README](https://github.com/collectiveidea/interactor/blob/master/README.md) for more information.
|
44
52
|
|
53
|
+
### Configuration
|
54
|
+
Metaractor is meant to be extensible (hence the 'meta'). You can add additional modules in the following way:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# This is an example from Outstand's production app to add some sidekiq magic.
|
58
|
+
# Feel free to place this in start up code or a Rails initializer.
|
59
|
+
Metaractor.configure do |config|
|
60
|
+
config.prepend_module Metaractor::SidekiqCallbacks
|
61
|
+
config.include_module Metaractor::SidekiqBatch
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
### Required Parameters
|
66
|
+
Metaractor supports complex required parameter statements and you can chain these together in any manner using `and`, `or`, and `xor`.
|
67
|
+
```ruby
|
68
|
+
required and: [:token, or: [:recipient_id, :recipient] ]
|
69
|
+
```
|
70
|
+
|
71
|
+
### Optional Parameters
|
72
|
+
As optional parameters have no enforcement, they are merely advisory.
|
73
|
+
```ruby
|
74
|
+
optional :enable_logging
|
75
|
+
```
|
76
|
+
|
77
|
+
### Custom Validation
|
78
|
+
Metaractor supports doing custom validation before any user supplied before_hooks run.
|
79
|
+
```ruby
|
80
|
+
validate_parameters do
|
81
|
+
if context.foo == :bar
|
82
|
+
require_parameter :bar, message: 'optional missing parameter message'
|
83
|
+
end
|
84
|
+
|
85
|
+
unless context.user.admin?
|
86
|
+
add_parameter_error param: :user, message: 'User must be an admin'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
If you need to require a parameter from a `before_hook` for any reason, use the bang version of the method:
|
92
|
+
```ruby
|
93
|
+
before do
|
94
|
+
# Be careful with this approach as some user code may run before the parameter validation
|
95
|
+
require_parameter! :awesome if context.mode == :awesome
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
### Further Reading
|
100
|
+
For more examples of all of the above approaches, please see the specs.
|
101
|
+
|
45
102
|
## Development
|
46
103
|
|
47
104
|
- `docker build -t outstand/metaractor .`
|
@@ -50,7 +107,7 @@ See Interactor's [README](https://github.com/collectiveidea/interactor/blob/mast
|
|
50
107
|
To release a new version:
|
51
108
|
- Update the version number in `version.rb` and commit the result.
|
52
109
|
- `docker build -t outstand/metaractor .`
|
53
|
-
- `docker run -it --rm -v ~/.gitconfig:/
|
110
|
+
- `docker run -it --rm -v ~/.gitconfig:/home/metaractor/.gitconfig -v ~/.gitconfig.user:/home/metaractor/.gitconfig.user -v ~/.ssh/id_rsa:/home/metaractor/.ssh/id_rsa -v ~/.gem:/home/metaractor/.gem outstand/metaractor rake release`
|
54
111
|
|
55
112
|
## Contributing
|
56
113
|
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
version: '3.6'
|
2
|
+
services:
|
3
|
+
metaractor:
|
4
|
+
build: .
|
5
|
+
image: outstand/metaractor:dev
|
6
|
+
stdin_open: true
|
7
|
+
tty: true
|
8
|
+
volumes:
|
9
|
+
- bundler-data:/usr/local/bundle
|
10
|
+
- .:/metaractor
|
11
|
+
release:
|
12
|
+
image: outstand/metaractor:dev
|
13
|
+
stdin_open: true
|
14
|
+
tty: true
|
15
|
+
command: rake release
|
16
|
+
volumes:
|
17
|
+
- bundler-data:/usr/local/bundle
|
18
|
+
- ~/.gitconfig:/home/metaractor/.gitconfig
|
19
|
+
- ~/.gitconfig.user:/home/metaractor/.gitconfig.user
|
20
|
+
- ~/.ssh/id_rsa:/home/metaractor/.ssh/id_rsa
|
21
|
+
- ~/.gem:/home/metaractor/.gem
|
22
|
+
|
23
|
+
volumes:
|
24
|
+
bundler-data:
|
data/docker-entrypoint.sh
CHANGED
@@ -1,12 +1,20 @@
|
|
1
|
-
#!/bin/
|
1
|
+
#!/bin/sh
|
2
2
|
set -e
|
3
3
|
|
4
|
-
if [ "$
|
5
|
-
|
4
|
+
if [ "$(which "$1")" = '' ]; then
|
5
|
+
if [ "$(ls -A /usr/local/bundle/bin)" = '' ]; then
|
6
|
+
echo 'command not in path and bundler not initialized'
|
7
|
+
echo 'running bundle install'
|
8
|
+
su-exec metaractor bundle install
|
9
|
+
fi
|
6
10
|
fi
|
7
11
|
|
8
12
|
if [ "$1" = 'bundle' ]; then
|
9
|
-
set --
|
13
|
+
set -- su-exec metaractor "$@"
|
14
|
+
elif ls /usr/local/bundle/bin | grep -q "\b$1\b"; then
|
15
|
+
set -- su-exec metaractor bundle exec "$@"
|
16
|
+
|
17
|
+
su-exec metaractor ash -c 'bundle check || bundle install'
|
10
18
|
fi
|
11
19
|
|
12
20
|
exec "$@"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Metaractor
|
2
|
+
module ChainFailures
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
around :chain_nested_failures
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def chain_nested_failures(interactor)
|
10
|
+
interactor.call
|
11
|
+
rescue Interactor::Failure => e
|
12
|
+
context.fail_from_context(context: e.context)
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Metaractor
|
2
|
+
module ContextErrors
|
3
|
+
def errors
|
4
|
+
if super.nil?
|
5
|
+
self.errors = []
|
6
|
+
end
|
7
|
+
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def fail_with_error!(message:)
|
12
|
+
add_error(message: message)
|
13
|
+
fail!
|
14
|
+
end
|
15
|
+
|
16
|
+
def fail_with_errors!(messages:)
|
17
|
+
add_errors(messages: messages)
|
18
|
+
fail!
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_error(message:)
|
22
|
+
add_errors(messages: Array(message))
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_errors(messages:)
|
26
|
+
self.errors += messages
|
27
|
+
end
|
28
|
+
|
29
|
+
def error_messages
|
30
|
+
errors.join("\n")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Interactor::Context.send(:include, Metaractor::ContextErrors)
|
data/lib/metaractor/errors.rb
CHANGED
@@ -1,39 +1,28 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
module Metaractor
|
2
4
|
class Error < StandardError; end
|
3
5
|
class InvalidError < Error; end
|
4
6
|
|
5
7
|
module Errors
|
6
|
-
def
|
7
|
-
|
8
|
-
before :initialize_errors_array
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize_errors_array
|
13
|
-
context.errors ||= []
|
14
|
-
end
|
15
|
-
|
16
|
-
def fail_with_error!(message:)
|
17
|
-
add_error(message: message)
|
18
|
-
context.fail!
|
8
|
+
def fail_with_error!(*args)
|
9
|
+
context.fail_with_error!(*args)
|
19
10
|
end
|
20
11
|
|
21
|
-
def fail_with_errors!(
|
22
|
-
|
23
|
-
context.fail!
|
12
|
+
def fail_with_errors!(*args)
|
13
|
+
context.fail_with_errors!(*args)
|
24
14
|
end
|
25
15
|
|
26
|
-
def add_error(
|
27
|
-
|
16
|
+
def add_error(*args)
|
17
|
+
context.add_error(*args)
|
28
18
|
end
|
29
19
|
|
30
|
-
def add_errors(
|
31
|
-
context.
|
32
|
-
context.errors += messages
|
20
|
+
def add_errors(*args)
|
21
|
+
context.add_errors(*args)
|
33
22
|
end
|
34
23
|
|
35
24
|
def error_messages
|
36
|
-
context.
|
25
|
+
context.error_messages
|
37
26
|
end
|
38
27
|
end
|
39
28
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Metaractor
|
2
|
+
module FailFromContext
|
3
|
+
def fail_from_context(context:)
|
4
|
+
return if context.equal?(self)
|
5
|
+
|
6
|
+
invalidate! if context.invalid?
|
7
|
+
add_errors(messages: context.errors)
|
8
|
+
@failure = true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Interactor::Context.send(:include, Metaractor::FailFromContext)
|
@@ -99,8 +99,6 @@ module Metaractor
|
|
99
99
|
|
100
100
|
case operator
|
101
101
|
when :or
|
102
|
-
# We can't test for #one? here as that breaks interactors with the same setup sharing a context.
|
103
|
-
# This happens in almost all of our organizers.
|
104
102
|
return valids.any?, "(#{messages.join(' or ')})"
|
105
103
|
when :xor
|
106
104
|
return valids.one?, "(#{messages.join(' xor ')})"
|
data/lib/metaractor/version.rb
CHANGED
data/lib/metaractor.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'metaractor/version'
|
2
2
|
require 'interactor'
|
3
3
|
require 'metaractor/errors'
|
4
|
+
require 'metaractor/context_errors'
|
4
5
|
require 'metaractor/parameters'
|
5
6
|
require 'metaractor/run_with_context'
|
6
7
|
require 'metaractor/context_validity'
|
8
|
+
require 'metaractor/chain_failures'
|
9
|
+
require 'metaractor/fail_from_context'
|
7
10
|
|
8
11
|
module Metaractor
|
9
12
|
def self.included(base)
|
@@ -36,7 +39,8 @@ module Metaractor
|
|
36
39
|
[
|
37
40
|
{ module: Metaractor::Errors, method: :include },
|
38
41
|
{ module: Metaractor::Parameters, method: :include },
|
39
|
-
{ module: Metaractor::RunWithContext, method: :include }
|
42
|
+
{ module: Metaractor::RunWithContext, method: :include },
|
43
|
+
{ module: Metaractor::ChainFailures, method: :include }
|
40
44
|
]
|
41
45
|
end
|
42
46
|
|
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: 1.1.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:
|
11
|
+
date: 2018-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interactor
|
@@ -80,10 +80,14 @@ files:
|
|
80
80
|
- LICENSE
|
81
81
|
- README.md
|
82
82
|
- Rakefile
|
83
|
+
- docker-compose.yml
|
83
84
|
- docker-entrypoint.sh
|
84
85
|
- lib/metaractor.rb
|
86
|
+
- lib/metaractor/chain_failures.rb
|
87
|
+
- lib/metaractor/context_errors.rb
|
85
88
|
- lib/metaractor/context_validity.rb
|
86
89
|
- lib/metaractor/errors.rb
|
90
|
+
- lib/metaractor/fail_from_context.rb
|
87
91
|
- lib/metaractor/parameters.rb
|
88
92
|
- lib/metaractor/run_with_context.rb
|
89
93
|
- lib/metaractor/version.rb
|
@@ -108,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
112
|
version: '0'
|
109
113
|
requirements: []
|
110
114
|
rubyforge_project:
|
111
|
-
rubygems_version: 2.
|
115
|
+
rubygems_version: 2.7.7
|
112
116
|
signing_key:
|
113
117
|
specification_version: 4
|
114
118
|
summary: Adds parameter validation and error control to interactor
|