active_operation 0.2.0 → 1.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 +5 -5
- data/.github/workflows/testing.yml +26 -0
- data/.ruby-version +1 -0
- data/LICENSE.txt +1 -1
- data/README.md +44 -11
- data/active_operation.gemspec +5 -5
- data/dev.yml +7 -0
- data/lib/active_operation/base.rb +31 -0
- data/lib/active_operation/matcher/execution.rb +2 -0
- data/lib/active_operation/pipeline.rb +2 -0
- data/lib/active_operation/version.rb +1 -1
- data/lib/active_operation.rb +1 -0
- data/lib/generators/active_operation/install/install_generator.rb +2 -1
- data/lib/generators/active_operation/operation/operation_generator.rb +4 -1
- data/lib/generators/rspec/operation/operation_generator.rb +12 -0
- data/lib/generators/test_unit/operation/operation_generator.rb +12 -0
- data/support/templates/{application_operation.rb → application_operation.rb.erb} +1 -0
- data/support/templates/{operation.rb → operation.rb.erb} +2 -1
- data/support/templates/operation_spec.rb.erb +8 -0
- data/support/templates/operation_test.rb.erb +10 -0
- metadata +25 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0af2d62196c5a9ae917f9071afe1cc8b861929b75d9508f1f6193e8a87509f07
|
4
|
+
data.tar.gz: 15861fe07258fa8a11bacdc0d9c578da175070bba359122cf8446fce8958ea3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a16400a73363829404d5767b189061319bb76a620af86b30af62ebf7537d90344ca7ab167cd27ad92fb1230c0779e1ab5c1ae0b32f90d4472647b490d21ecffa
|
7
|
+
data.tar.gz: 661062ef56212fc48c83cdd512728148c4b967bea8991f87ae60f845420eb5b851faa9b0c862a6b8a150a3af59c5cf26d2322eb729c9f077b6eedd8a2513b06f
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: Testing
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
pull_request:
|
7
|
+
branches: [master]
|
8
|
+
workflow_dispatch:
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
test:
|
12
|
+
name: Ruby v${{ matrix.ruby_version}}
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
strategy:
|
15
|
+
matrix:
|
16
|
+
ruby_version: [2.6.9, 2.7.5, 3.0.3]
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- name: Set up Ruby
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby_version }}
|
23
|
+
- name: Install dependencies
|
24
|
+
run: bundle install
|
25
|
+
- name: Run tests
|
26
|
+
run: bundle exec rake
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.3
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2016 Konstantin Tennhard
|
3
|
+
Copyright (c) 2016-2021 Konstantin Tennhard
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
# ActiveOperation
|
2
|
+
|
2
3
|
[](https://rubygems.org/gems/active_operation)
|
3
4
|
[](https://rubygems.org/gems/active_operation)
|
4
5
|
|
5
6
|
`ActiveOperation` is a micro-framework for modelling business processes.
|
6
7
|
It is the perfect companion for any Rails application.
|
7
|
-
The
|
8
|
+
The main idea behind an operation is to move code that traditionally either lives in a controller or a model into a dedicated object.
|
9
|
+
Multiple operations can be combined into a pipeline.
|
10
|
+
This helps with structuring large business processes and aids reusability.
|
8
11
|
|
9
12
|
## Installation
|
10
13
|
|
11
14
|
Add this line to your application's Gemfile:
|
12
15
|
|
13
16
|
```ruby
|
14
|
-
gem 'active_operation'
|
17
|
+
gem 'active_operation'
|
15
18
|
```
|
16
19
|
|
17
20
|
And then execute:
|
@@ -20,7 +23,7 @@ And then execute:
|
|
20
23
|
$ bundle
|
21
24
|
```
|
22
25
|
|
23
|
-
Or install it
|
26
|
+
Or install it manually as:
|
24
27
|
|
25
28
|
```
|
26
29
|
$ gem install active_operation
|
@@ -28,20 +31,24 @@ $ gem install active_operation
|
|
28
31
|
|
29
32
|
### Rails
|
30
33
|
|
31
|
-
|
34
|
+
Run the the install generator to initialize a base operation:
|
32
35
|
|
33
36
|
```
|
34
37
|
rails g active_operation:install
|
35
38
|
```
|
36
39
|
|
37
|
-
|
40
|
+
Then generate the desired operation:
|
38
41
|
|
39
42
|
```
|
40
|
-
rails g active_operation:operation
|
43
|
+
rails g active_operation:operation signup/create_user
|
41
44
|
```
|
42
45
|
|
43
46
|
## Usage
|
44
47
|
|
48
|
+
We will first look at defining and using a single operation and then explore how to combine multiple operations into a pipeline.
|
49
|
+
|
50
|
+
### Defining and using a single operation
|
51
|
+
|
45
52
|
To define an operation, create a new class and inherit from `ActiveOperation::Base`.
|
46
53
|
The input arguments of an operation are defined using the `input` statement.
|
47
54
|
These statements describe the arguments the initializer takes.
|
@@ -76,8 +83,8 @@ end
|
|
76
83
|
```
|
77
84
|
|
78
85
|
To execute an operation, instantiate it and invoke the `#call` method.
|
79
|
-
|
80
|
-
For convenience, operations also expose a `.call` class method, which instantiates the operation, runs it and returns
|
86
|
+
This method will return the operation's output, which is also available through the `#output` method.
|
87
|
+
For convenience, operations also expose a `.call` class method, which instantiates the operation, runs it and returns its output.
|
81
88
|
|
82
89
|
Operations go through different states during their lifecycle.
|
83
90
|
After executing an operation, the state can be used for branching purposes.
|
@@ -106,17 +113,43 @@ class UsersController < ApplicationController
|
|
106
113
|
end
|
107
114
|
```
|
108
115
|
|
116
|
+
### Defining and using pipelines
|
117
|
+
|
118
|
+
Continuing with the example above, given the two operations, `User::Signup` and `Email::SendWelcomeEmail`, a pipeline can be defined as follows:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class OnboardUser < ActiveSupport::Pipeline
|
122
|
+
use User::Signup
|
123
|
+
use Email::SendWelcomeEmail
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
The pipeline derives its inputs from the first operation – in this case `User::Signup`.
|
128
|
+
Similarly, the pipeline's output is simply the output of the last operation.
|
129
|
+
All operations beyond the first operation are expected to take its predecessors output as input.
|
130
|
+
In the example above, `User::Signup` produces a `User` record that `Email::SendWelcomeEmail` takes as input.
|
131
|
+
|
132
|
+
Pipeline themselves are operations and can therefore be invoked like any other operations.
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
OnboardUser.call(email: "john@doe.com", password: "123456")
|
136
|
+
```
|
137
|
+
|
138
|
+
Furthermore, since pipelines are operations themselves, they can also be used within other pipelines.
|
139
|
+
|
109
140
|
## Development
|
110
141
|
|
111
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
142
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
143
|
+
Then, run `rake spec` to run the tests.
|
144
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
112
145
|
|
113
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
146
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
147
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
114
148
|
|
115
149
|
## Contributing
|
116
150
|
|
117
151
|
Bug reports and pull requests are welcome on GitHub at https://github.com/t6d/active_operation.
|
118
152
|
|
119
|
-
|
120
153
|
## License
|
121
154
|
|
122
155
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/active_operation.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["konstantin@tennhard.net", "sebastian.szturo@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{ActiveOperation is a micro-framework for modelling business processes.}
|
13
|
-
spec.homepage = "https://
|
13
|
+
spec.homepage = "https://github.com/t6d/active_operation"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_runtime_dependency "activesupport", ">
|
22
|
-
spec.add_runtime_dependency "smart_properties", "~> 1.
|
21
|
+
spec.add_runtime_dependency "activesupport", "> 5.0"
|
22
|
+
spec.add_runtime_dependency "smart_properties", "~> 1.17"
|
23
23
|
|
24
|
-
spec.add_development_dependency "bundler", "~>
|
25
|
-
spec.add_development_dependency "rake", "~>
|
24
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
25
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
26
26
|
spec.add_development_dependency "rspec", "~> 3.0"
|
27
27
|
spec.add_development_dependency "pry"
|
28
28
|
end
|
data/dev.yml
ADDED
@@ -20,6 +20,37 @@ class ActiveOperation::Base
|
|
20
20
|
new(*args).call
|
21
21
|
end
|
22
22
|
|
23
|
+
def from_proc(execute)
|
24
|
+
Class.new(self) do
|
25
|
+
positional_arguments = []
|
26
|
+
keyword_arguments = []
|
27
|
+
|
28
|
+
execute.parameters.each do |type, name|
|
29
|
+
case type
|
30
|
+
when :req
|
31
|
+
input name, type: :positional, required: true
|
32
|
+
positional_arguments << name
|
33
|
+
when :keyreq
|
34
|
+
input name, type: :keyword, required: true
|
35
|
+
keyword_arguments << name
|
36
|
+
else
|
37
|
+
raise ArgumentError, "Argument type not supported: #{type}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
define_method(:execute) do
|
42
|
+
args = positional_arguments.map { |name| self[name] }
|
43
|
+
opts = keyword_arguments.map { |name| [name, self[name]] }.to_h
|
44
|
+
|
45
|
+
if opts.empty?
|
46
|
+
execute.call(*args)
|
47
|
+
else
|
48
|
+
execute.call(*args, **opts)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
23
54
|
def call(*args)
|
24
55
|
perform(*args)
|
25
56
|
end
|
data/lib/active_operation.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rails/generators/base'
|
2
3
|
require 'rails/generators/active_record'
|
3
4
|
|
@@ -7,7 +8,7 @@ module ActiveOperation
|
|
7
8
|
source_root File.expand_path('../../../../../support/templates', __FILE__)
|
8
9
|
|
9
10
|
def create_application_operation
|
10
|
-
template 'application_operation.rb', 'app/operations/application_operation.rb'
|
11
|
+
template 'application_operation.rb.erb', 'app/operations/application_operation.rb'
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rails/generators/base'
|
2
3
|
require 'rails/generators/active_record'
|
3
4
|
|
@@ -6,8 +7,10 @@ module ActiveOperation
|
|
6
7
|
class OperationGenerator < Rails::Generators::NamedBase
|
7
8
|
source_root File.expand_path('../../../../../support/templates', __FILE__)
|
8
9
|
|
10
|
+
hook_for :test_framework
|
11
|
+
|
9
12
|
def create_operation
|
10
|
-
template 'operation.rb', File.join('app/operations', class_path, "#{file_name}.rb")
|
13
|
+
template 'operation.rb.erb', File.join('app/operations', class_path, "#{file_name}.rb")
|
11
14
|
end
|
12
15
|
end
|
13
16
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Rspec
|
3
|
+
module Generators
|
4
|
+
class OperationGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path('../../../../../support/templates', __FILE__)
|
6
|
+
|
7
|
+
def copy_files
|
8
|
+
template 'operation_spec.rb.erb', File.join('spec/operations', class_path, "#{file_name}_spec.rb")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module TestUnit
|
3
|
+
module Generators
|
4
|
+
class OperationGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path('../../../../../support/templates', __FILE__)
|
6
|
+
|
7
|
+
def copy_files
|
8
|
+
template 'operation_test.rb.erb', File.join('test/operations', class_path, "#{file_name}_test.rb")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Tennhard
|
8
8
|
- Sebastian Szturo
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-12-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -17,56 +17,56 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '5.0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '5.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: smart_properties
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '1.
|
34
|
+
version: '1.17'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '1.
|
41
|
+
version: '1.17'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: bundler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '2.0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '2.0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rake
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '13.0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '13.0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rspec
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
|
-
description:
|
98
|
+
description:
|
99
99
|
email:
|
100
100
|
- konstantin@tennhard.net
|
101
101
|
- sebastian.szturo@gmail.com
|
@@ -103,8 +103,10 @@ executables: []
|
|
103
103
|
extensions: []
|
104
104
|
extra_rdoc_files: []
|
105
105
|
files:
|
106
|
+
- ".github/workflows/testing.yml"
|
106
107
|
- ".gitignore"
|
107
108
|
- ".rspec"
|
109
|
+
- ".ruby-version"
|
108
110
|
- ".travis.yml"
|
109
111
|
- Gemfile
|
110
112
|
- LICENSE.txt
|
@@ -113,6 +115,7 @@ files:
|
|
113
115
|
- active_operation.gemspec
|
114
116
|
- bin/console
|
115
117
|
- bin/setup
|
118
|
+
- dev.yml
|
116
119
|
- lib/active_operation.rb
|
117
120
|
- lib/active_operation/base.rb
|
118
121
|
- lib/active_operation/input.rb
|
@@ -125,13 +128,17 @@ files:
|
|
125
128
|
- lib/generators/active_operation/install/install_generator.rb
|
126
129
|
- lib/generators/active_operation/operation/USAGE
|
127
130
|
- lib/generators/active_operation/operation/operation_generator.rb
|
128
|
-
-
|
129
|
-
-
|
130
|
-
|
131
|
+
- lib/generators/rspec/operation/operation_generator.rb
|
132
|
+
- lib/generators/test_unit/operation/operation_generator.rb
|
133
|
+
- support/templates/application_operation.rb.erb
|
134
|
+
- support/templates/operation.rb.erb
|
135
|
+
- support/templates/operation_spec.rb.erb
|
136
|
+
- support/templates/operation_test.rb.erb
|
137
|
+
homepage: https://github.com/t6d/active_operation
|
131
138
|
licenses:
|
132
139
|
- MIT
|
133
140
|
metadata: {}
|
134
|
-
post_install_message:
|
141
|
+
post_install_message:
|
135
142
|
rdoc_options: []
|
136
143
|
require_paths:
|
137
144
|
- lib
|
@@ -146,9 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
153
|
- !ruby/object:Gem::Version
|
147
154
|
version: '0'
|
148
155
|
requirements: []
|
149
|
-
|
150
|
-
|
151
|
-
signing_key:
|
156
|
+
rubygems_version: 3.2.32
|
157
|
+
signing_key:
|
152
158
|
specification_version: 4
|
153
159
|
summary: ActiveOperation is a micro-framework for modelling business processes.
|
154
160
|
test_files: []
|