makwa 0.1.0 → 0.2.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/.gitignore +3 -1
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +1 -1
- data/Rakefile +10 -1
- data/doc/how_to_release_new_version.md +14 -0
- data/lib/makwa/interaction.rb +80 -0
- data/lib/makwa/returning_interaction.rb +93 -0
- data/lib/makwa/version.rb +1 -1
- data/lib/makwa.rb +7 -3
- data/makwa.gemspec +15 -14
- metadata +52 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2da52aacefd38c1922e5e8b48277fca8106997a068b682d93698bd9e444da41f
|
4
|
+
data.tar.gz: a506c6b8ae75f3d093afdf455b84733f0d0984843561dde099bbbb9ffddc7e91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8784e825031765550dce4b56c82aae5a872d403cf14f444cdb0a2afb00fd2603e14f28910a92f3415b60df351820a17f738264eb6bf3bacd050f3ac21ee79c43
|
7
|
+
data.tar.gz: ea5dde94eca0a95abda600e4bd8f129dc63413a855cdf3ffb9ee5f15176ee7f1edcd368216265aff272def00ca4795b647f7667bd6bbe58ec3a742ab361274bd
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
CHANGED
data/Rakefile
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
|
-
|
4
|
+
|
5
|
+
require "rake/testtask"
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |t|
|
8
|
+
t.libs << "test"
|
9
|
+
t.pattern = "test/**/*_test.rb"
|
10
|
+
t.verbose = false
|
11
|
+
end
|
12
|
+
|
13
|
+
task default: :test
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# How to release a new version
|
2
|
+
|
3
|
+
* Make changes to the code
|
4
|
+
* Update tests as needed
|
5
|
+
* Update CHANGELOG.md
|
6
|
+
* Commit changes
|
7
|
+
* Prepare new release
|
8
|
+
* Bump version via one of
|
9
|
+
* `gem bump --tag --version major`
|
10
|
+
* `gem bump --tag --version minor`
|
11
|
+
* `gem bump --tag --version patch`
|
12
|
+
* The bump command will commit the new version and tag the commit.
|
13
|
+
* Distribute new release
|
14
|
+
* `gem release` - This will push the new release to rubygems.org.
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Makwa
|
4
|
+
class Interaction < ::ActiveInteraction::Base
|
5
|
+
class Interrupt < Object.const_get("::ActiveInteraction::Interrupt")
|
6
|
+
end
|
7
|
+
|
8
|
+
#
|
9
|
+
# Safely checking for errors
|
10
|
+
#
|
11
|
+
|
12
|
+
# Use this instead of `outcome.invalid?` (which is destructive and clears errors)
|
13
|
+
delegate :any?, to: :errors, prefix: true # def errors_any?
|
14
|
+
# Use this instead of `outcome.valid?` (which is destructive and clears errors)
|
15
|
+
delegate :empty?, to: :errors, prefix: true # def errors_empty?
|
16
|
+
|
17
|
+
#
|
18
|
+
# Halting of execution
|
19
|
+
#
|
20
|
+
|
21
|
+
# Exits early if there are any errors.
|
22
|
+
def return_if_errors!
|
23
|
+
raise(Interrupt, errors) if errors_any?
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Logging interaction execution
|
28
|
+
#
|
29
|
+
|
30
|
+
# Log execution of interaction, caller, and inputs
|
31
|
+
set_callback :type_check, :before, ->(interaction) {
|
32
|
+
debug("Executing interaction #{interaction.class.name} #{interaction.id_marker}")
|
33
|
+
calling_interaction = interaction.calling_interaction
|
34
|
+
debug(" ↳ called from #{calling_interaction} #{interaction.id_marker}") if calling_interaction.present?
|
35
|
+
# The next two lines offer two ways of printing inputs: Either truncated, or full. Adjust as needed.
|
36
|
+
# truncated_inputs = interaction.inputs.inspect.truncate_in_the_middle(2000, omission: "\n... [inputs truncated] ...\n")
|
37
|
+
truncated_inputs = interaction.inputs.inspect
|
38
|
+
debug(" ↳ inputs: #{truncated_inputs} #{interaction.id_marker}")
|
39
|
+
}
|
40
|
+
|
41
|
+
# Log interaction's outcome and errors if any.
|
42
|
+
set_callback :execute, :after, ->(interaction) {
|
43
|
+
if interaction.errors_empty?
|
44
|
+
debug(" ↳ outcome: succeeded (id##{interaction.object_id})")
|
45
|
+
else
|
46
|
+
debug(" ↳ outcome: failed (id##{interaction.object_id})")
|
47
|
+
debug(" ↳ errors: #{interaction.errors.details} (id##{interaction.object_id})")
|
48
|
+
end
|
49
|
+
}
|
50
|
+
|
51
|
+
# @return [Array<String>] the callstack containing interactions only, starting with the immediate caller.
|
52
|
+
def calling_interactions
|
53
|
+
@calling_interactions ||= caller.find_all { |e|
|
54
|
+
e.index("/app/interactions/") && !e.index(__FILE__) && !e.index("/returning_interaction.rb")
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [String] the backtrace entry for the immediately calling interaction (first item in calling_interactions).
|
59
|
+
def calling_interaction
|
60
|
+
@calling_interaction ||= calling_interactions.first&.split("/interactions/")&.last || ""
|
61
|
+
end
|
62
|
+
|
63
|
+
# The standard method for all logging output. Turn this on for detailed interaction logging.
|
64
|
+
def debug(txt)
|
65
|
+
# puts indent + txt
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [String] a marker that identifies an interaction instance by its Ruby object_id. This is helpful
|
69
|
+
# when following an execution log with nested or interleaved interaction log lines.
|
70
|
+
def id_marker
|
71
|
+
"(id##{object_id})"
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [String] a prefix that indents each debug line according to the level of interactions nesting.
|
75
|
+
def indent
|
76
|
+
lvl = [0, calling_interactions.count].max
|
77
|
+
" " * lvl
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Makwa
|
4
|
+
# @abstract Override {#execute_returning} and call {#returning} in the class body, passing in the symbol
|
5
|
+
# of the input you want returned. Guaranteed to return the returning input, with interaction errors
|
6
|
+
# merged into it.
|
7
|
+
class ReturningInteraction < ::Makwa::Interaction
|
8
|
+
class ReturnFilterInexistent < StandardError; end
|
9
|
+
|
10
|
+
class ReturningFilterNotSpecified < StandardError; end
|
11
|
+
|
12
|
+
class NotActiveModelErrorable < StandardError; end
|
13
|
+
|
14
|
+
define_callbacks(:execute_returning)
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# @param (see ActiveInteraction::Runnable#initialize)
|
18
|
+
#
|
19
|
+
# @return (see ReturningInteraction#run_returning!)
|
20
|
+
def run_returning!(*args)
|
21
|
+
new(*args).send(:run_returning!)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param return_filter [Symbol] Name of the input filter to be returned
|
25
|
+
def returning(return_filter)
|
26
|
+
@return_filter = return_filter
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @abstract
|
31
|
+
#
|
32
|
+
# @raise [NotImplementedError]
|
33
|
+
def execute_returning
|
34
|
+
raise NotImplementedError, "You need to implemented the method #execute_returning in your interaction."
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @return [Object]
|
40
|
+
def run_returning!
|
41
|
+
@_interaction_result = return_input # {#result=} has side-effects
|
42
|
+
raise ReturningFilterNotSpecified unless self.class.instance_variable_defined?(:@return_filter)
|
43
|
+
raise ReturnFilterInexistent unless result
|
44
|
+
raise NotActiveModelErrorable unless result.respond_to?(:errors) && result.errors.respond_to?(:merge!)
|
45
|
+
|
46
|
+
# Run validations (explicitly, don't rely on #valid?)
|
47
|
+
validate
|
48
|
+
if errors_any?
|
49
|
+
# Add errors and values to the result object (so that the form can render them) and return the result object
|
50
|
+
return result
|
51
|
+
.tap { |r| r.errors.merge!(errors) }
|
52
|
+
.tap { |r| r.assign_attributes(inputs.except(@return_filter)) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Otherwise run the body of the interaction (along with any callbacks) ...
|
56
|
+
run_callbacks(:execute_returning) do
|
57
|
+
execute_returning
|
58
|
+
rescue ::Makwa::Interaction::Interrupt
|
59
|
+
# Do nothing
|
60
|
+
end
|
61
|
+
|
62
|
+
# ... and return the result, merging in any errors added in the body of the interaction that are not duplicates.
|
63
|
+
# Duplicates would occur if, for example, the body of the interaction calls
|
64
|
+
# `errors.merge!(<returning_filter>.errors)` as is often done in non-returning interactions.
|
65
|
+
result.tap do |r|
|
66
|
+
errors.each do |e|
|
67
|
+
r.errors.add(e.attribute, e.message) unless r.errors.added?(e.attribute, e.message)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [Object]
|
73
|
+
def return_input
|
74
|
+
@return_input ||= inputs[self.class.instance_variable_get(:@return_filter)]
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param other [Class] The other interaction.
|
78
|
+
#
|
79
|
+
# @return (see #result)
|
80
|
+
def compose(other, *args)
|
81
|
+
@_interaction_result = other.run_returning!(*args)
|
82
|
+
|
83
|
+
if block_given?
|
84
|
+
errors.merge!(@_interaction_result.errors)
|
85
|
+
yield @_interaction_result
|
86
|
+
end
|
87
|
+
|
88
|
+
@_interaction_result
|
89
|
+
rescue NotImplementedError
|
90
|
+
super(other, *args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/makwa/version.rb
CHANGED
data/lib/makwa.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "active_interaction"
|
4
4
|
|
5
5
|
module Makwa
|
6
|
-
class Error < StandardError; end
|
7
|
-
# Your code goes here...
|
8
6
|
end
|
7
|
+
|
8
|
+
# Dependency boundary
|
9
|
+
|
10
|
+
require "makwa/interaction"
|
11
|
+
require "makwa/returning_interaction"
|
12
|
+
require "makwa/version"
|
data/makwa.gemspec
CHANGED
@@ -3,14 +3,18 @@
|
|
3
3
|
require_relative "lib/makwa/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name
|
7
|
-
spec.version
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
spec.name = "makwa"
|
7
|
+
spec.version = Makwa::VERSION
|
8
|
+
{
|
9
|
+
"Jo Hund" => "jo@animikii.com",
|
10
|
+
"Fabio Papa" => "fabio.papa@animikii.com"
|
11
|
+
}.tap do |hash|
|
12
|
+
spec.authors = hash.keys
|
13
|
+
spec.email = hash.values
|
14
|
+
end
|
15
|
+
spec.summary = "Interactions for Ruby on Rails apps."
|
16
|
+
spec.homepage = "https://github.com/animikii/makwa"
|
17
|
+
spec.license = "MIT"
|
14
18
|
spec.required_ruby_version = ">= 2.4.0"
|
15
19
|
|
16
20
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -22,13 +26,10 @@ Gem::Specification.new do |spec|
|
|
22
26
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
24
28
|
end
|
25
|
-
spec.bindir = "exe"
|
26
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
27
29
|
spec.require_paths = ["lib"]
|
28
30
|
|
29
|
-
|
30
|
-
# spec.add_dependency "example-gem", "~> 1.0"
|
31
|
+
spec.add_dependency "active_interaction", "~> 4.0"
|
31
32
|
|
32
|
-
|
33
|
-
|
33
|
+
spec.add_development_dependency "standard"
|
34
|
+
spec.add_development_dependency "byebug"
|
34
35
|
end
|
metadata
CHANGED
@@ -1,18 +1,62 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: makwa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jo Hund
|
8
|
+
- Fabio Papa
|
8
9
|
autorequire:
|
9
|
-
bindir:
|
10
|
+
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2021-
|
12
|
-
dependencies:
|
12
|
+
date: 2021-10-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: active_interaction
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '4.0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '4.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: standard
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: byebug
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
13
56
|
description:
|
14
57
|
email:
|
15
|
-
-
|
58
|
+
- jo@animikii.com
|
59
|
+
- fabio.papa@animikii.com
|
16
60
|
executables: []
|
17
61
|
extensions: []
|
18
62
|
extra_rdoc_files: []
|
@@ -25,7 +69,10 @@ files:
|
|
25
69
|
- Rakefile
|
26
70
|
- bin/console
|
27
71
|
- bin/setup
|
72
|
+
- doc/how_to_release_new_version.md
|
28
73
|
- lib/makwa.rb
|
74
|
+
- lib/makwa/interaction.rb
|
75
|
+
- lib/makwa/returning_interaction.rb
|
29
76
|
- lib/makwa/version.rb
|
30
77
|
- makwa.gemspec
|
31
78
|
homepage: https://github.com/animikii/makwa
|