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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8bdc777077d09ca35ca998b494ce9b74e56883e3
4
- data.tar.gz: 1d1645bd315927baf24ccbf66a7bc8ee18ff5aed
2
+ SHA256:
3
+ metadata.gz: 61aa5597f77391b54b18d7a7d31e6b3cef5d00c844702fc3e1ef06c2dc8b0b1d
4
+ data.tar.gz: 5749efb4aa913aa4e4157e1213abedf689766add06df57544a41ac85aae47b0d
5
5
  SHA512:
6
- metadata.gz: 0309b7ea31e0629a4f3c076ad489a74e3be15e5ff5252f48743371c0ff55f9de1bacff22bd96c8c9d954749000ebbc525077a518bb7e8b963ddfb9755fb9bf1d
7
- data.tar.gz: 80c63031ecbc6553f5e121b7a6eddffbb5051d39b336661c0978a006e2cb628adee35b83324bb427dee68cd6d9a4698322a364682fa6236ff9859f71ebebf3a1
6
+ metadata.gz: 2c0d070919763827f78dee03c6667022faaf0b1882b65d527c1829f287b3ce7fa33efc91b8b55cb85e0edd1e808917b5d1b2e5d6833a151e33728b40f5df64d8
7
+ data.tar.gz: a5969b17f7cbe5c2f447e5b43dca00662e6bf8cdf23f96414fb0257d1b4aec4eaf1c02899dbf06947f582739995e015830d06b3857a65d36cfb8c5a260d259d4
data/Dockerfile CHANGED
@@ -1,48 +1,27 @@
1
- FROM ruby:2.3.1-alpine
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
- ENV GOSU_VERSION 1.9
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
- WORKDIR /metaractor
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
- ENV DUMB_INIT_SETSID 0
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:/root/.gitconfig -v ~/.gitconfig.user:/root/.gitconfig.user -v ~/.ssh/id_rsa:/root/.ssh/id_rsa -v ~/.gem:/root/.gem outstand/metaractor rake release`
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
 
@@ -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/dumb-init /bin/sh
1
+ #!/bin/sh
2
2
  set -e
3
3
 
4
- if [ "$1" = 'rspec' ] || [ "$1" = 'rake' ]; then
5
- set -- bundle exec "$@"
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 -- gosu metaractor "$@"
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)
@@ -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 self.included(base)
7
- base.class_eval do
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!(messages:)
22
- add_errors(messages: messages)
23
- context.fail!
12
+ def fail_with_errors!(*args)
13
+ context.fail_with_errors!(*args)
24
14
  end
25
15
 
26
- def add_error(message:)
27
- add_errors(messages: Array(message))
16
+ def add_error(*args)
17
+ context.add_error(*args)
28
18
  end
29
19
 
30
- def add_errors(messages:)
31
- context.errors ||= []
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.errors.join("\n")
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 ')})"
@@ -1,3 +1,3 @@
1
1
  module Metaractor
2
- VERSION = "0.5.0"
2
+ VERSION = "1.1.0"
3
3
  end
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: 0.5.0
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: 2016-06-04 00:00:00.000000000 Z
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.6.4
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