typed_operation 0.2.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -4
- data/lib/generators/USAGE +25 -0
- data/lib/generators/templates/operation.rb +35 -0
- data/lib/generators/templates/operation_test.rb +47 -0
- data/lib/generators/typed_operation/install/USAGE +21 -0
- data/lib/generators/typed_operation/install/install_generator.rb +23 -0
- data/lib/generators/typed_operation/install/templates/application_operation.rb +14 -0
- data/lib/generators/typed_operation_generator.rb +27 -0
- data/lib/typed_operation/base.rb +6 -7
- data/lib/typed_operation/railtie.rb +4 -0
- data/lib/typed_operation/version.rb +1 -1
- data/lib/typed_operation.rb +1 -2
- metadata +18 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c80a027434c29b23257b43e03eeb8acb61a3ac300a59e0c04068ffada1dd4aa6
|
4
|
+
data.tar.gz: 6b78a70b2a46710746129f8dac3a403bdc692c761c93f3ec111bf09efec8a70e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35baa03191cfa29e1786de975d7f8d2baf62040859922544f0d79109a8f088996521e85e3dce0c66bde1f7dd5bb2b62a5332cb7841a63a1ebe4b369d48005bb6
|
7
|
+
data.tar.gz: ebf8aea46fb0d3dcd72aa846b772f228aca21be2e04695989266218e9303e9b7760770d67f53f57ca231b41b7f502ad5145bf621a0648c6706b6e741a8e6c80e
|
data/README.md
CHANGED
@@ -1,13 +1,10 @@
|
|
1
1
|
# TypedOperation
|
2
|
-
Short description and motivation.
|
3
|
-
|
4
|
-
## Usage
|
5
2
|
|
6
3
|
An implementation of a Command pattern, which is callable, and can be partially applied (curried).
|
7
4
|
|
8
5
|
Inputs to the operation are specified as typed attributes using the `param` method.
|
9
6
|
|
10
|
-
|
7
|
+
Result format of the operation is up to you, but plays nicely with `Dry::Monads`.
|
11
8
|
|
12
9
|
### Examples:
|
13
10
|
|
@@ -15,6 +12,8 @@ A base operation class:
|
|
15
12
|
|
16
13
|
```ruby
|
17
14
|
class ApplicationOperation < ::TypedOperation::Base
|
15
|
+
include Dry::Monads[:result, :do]
|
16
|
+
|
18
17
|
param :initiator, ::RegisteredUser, allow_nil: true
|
19
18
|
|
20
19
|
private
|
@@ -96,6 +95,35 @@ Or install it yourself as:
|
|
96
95
|
$ gem install typed_operation
|
97
96
|
```
|
98
97
|
|
98
|
+
### Add an `ApplicationOperation` to your project
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
bin/rails g typed_operation:install
|
102
|
+
```
|
103
|
+
|
104
|
+
Use the `--dry_monads` switch to `include Dry::Monads[:result]` into your `ApplicationOperation` (don't forget to also
|
105
|
+
add `gem "dry-monads"` to your Gemfile)
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
bin/rails g typed_operation:install --dry_monads
|
109
|
+
```
|
110
|
+
|
111
|
+
## Generate a new Operation
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
bin/rails g typed_operation TestOperation
|
115
|
+
```
|
116
|
+
|
117
|
+
You can optionally specify the directory to generate the operation in:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
bin/rails g typed_operation TestOperation --path=app/operations
|
121
|
+
```
|
122
|
+
|
123
|
+
The default path is `app/operations`.
|
124
|
+
|
125
|
+
The generator will also create a test file.
|
126
|
+
|
99
127
|
## Contributing
|
100
128
|
Contribution directions go here.
|
101
129
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Operation Generator
|
2
|
+
===================
|
3
|
+
|
4
|
+
Description:
|
5
|
+
------------
|
6
|
+
This generator creates an 'TypedOperation' class that inherits from ApplicationOperation.
|
7
|
+
|
8
|
+
Command:
|
9
|
+
--------
|
10
|
+
rails generate typed_operation NAME [options]
|
11
|
+
|
12
|
+
Arguments:
|
13
|
+
----------
|
14
|
+
NAME: The class name of the Operation class to be generated, e.g. 'MyOperation'.
|
15
|
+
|
16
|
+
Options:
|
17
|
+
--------
|
18
|
+
--path=path/to/directory: The path to the directory in which the operation class should be generated. The generated class will be namespaced according to the provided path.
|
19
|
+
|
20
|
+
Example:
|
21
|
+
--------
|
22
|
+
rails generate typed_operation MyOperation --path=app/operations
|
23
|
+
|
24
|
+
This will create the following file:
|
25
|
+
app/operations/my_operation.rb
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
<% if namespace_name.present? %>
|
4
|
+
module <%= namespace_name %>
|
5
|
+
class <%= name %> < ::ApplicationOperation
|
6
|
+
# Replace with implementation...
|
7
|
+
param :my_param, String, convert: true
|
8
|
+
param :an_optional_param, Integer, allow_nil: true
|
9
|
+
|
10
|
+
def prepare
|
11
|
+
# Prepare...
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
# Perform...
|
16
|
+
"Hello World!"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
<% else %>
|
21
|
+
class <%= name %> < ::ApplicationOperation
|
22
|
+
# Replace with implementation...
|
23
|
+
param :my_param, String, convert: true
|
24
|
+
param :an_optional_param, Integer, allow_nil: true
|
25
|
+
|
26
|
+
def prepare
|
27
|
+
# Prepare...
|
28
|
+
end
|
29
|
+
|
30
|
+
def call
|
31
|
+
# Perform...
|
32
|
+
"Hello World!"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
<% end %>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
<% if namespace_name.present? %>
|
4
|
+
module <%= namespace_name %>
|
5
|
+
class <%= name %>Test < ActiveSupport::TestCase
|
6
|
+
def setup
|
7
|
+
@operation = <%= name %>.new(my_param: "test")
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'should raise ParameterError if my_param is nil' do
|
11
|
+
assert_raises(ParameterError) do
|
12
|
+
<%= name %>.new(my_param: nil)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'should convert my_param if it is not a string' do
|
17
|
+
assert_equal <%= name %>.new(my_param: 123).my_param, "123"
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'call returns after operation' do
|
21
|
+
result = @operation.call
|
22
|
+
assert_equal result, "Hello World!"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
<% else %>
|
27
|
+
class <%= name %>Test < ActiveSupport::TestCase
|
28
|
+
def setup
|
29
|
+
@operation = <%= name %>.new(my_param: "test")
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'should raise ParameterError if my_param is nil' do
|
33
|
+
assert_raises(ParameterError) do
|
34
|
+
<%= name %>.new(my_param: nil)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
test 'should convert my_param if it is not a string' do
|
39
|
+
assert_equal <%= name %>.new(my_param: 123).my_param, "123"
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'call returns after operation' do
|
43
|
+
result = @operation.call
|
44
|
+
assert_equal result, "Hello World!"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Install Generator
|
2
|
+
=================
|
3
|
+
|
4
|
+
Description:
|
5
|
+
------------
|
6
|
+
This generator installs a `ApplicationOperation` class which is your base class for all Operations.
|
7
|
+
|
8
|
+
Command:
|
9
|
+
--------
|
10
|
+
rails generate typed_operation:install
|
11
|
+
|
12
|
+
Options:
|
13
|
+
--------
|
14
|
+
--dry_monads: if specified the ApplicationOperation will include dry-monads Result and Do notation.
|
15
|
+
|
16
|
+
Example:
|
17
|
+
--------
|
18
|
+
rails generate typed_operation:install
|
19
|
+
|
20
|
+
This will create the following file:
|
21
|
+
app/operations/application_operation.rb
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/base"
|
4
|
+
|
5
|
+
module TypedOperation
|
6
|
+
module Install
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
class_option :dry_monads, type: :boolean, default: false
|
9
|
+
|
10
|
+
source_root File.expand_path("templates", __dir__)
|
11
|
+
|
12
|
+
def copy_application_operation_file
|
13
|
+
template "application_operation.rb", "app/operations/application_operation.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def include_dry_monads?
|
19
|
+
options[:dry_monads]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ApplicationOperation < ::TypedOperation::Base
|
4
|
+
<% if include_dry_monads? -%>
|
5
|
+
include Dry::Monads[:result, :do]
|
6
|
+
|
7
|
+
def call!
|
8
|
+
call.value!
|
9
|
+
end
|
10
|
+
|
11
|
+
<% end -%>
|
12
|
+
# Other common parameters & methods for Operations of this application...
|
13
|
+
# ...
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/named_base"
|
4
|
+
|
5
|
+
class TypedOperationGenerator < Rails::Generators::NamedBase
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
class_option :path, type: :string, default: "app/operations"
|
9
|
+
|
10
|
+
def generate_operation
|
11
|
+
template(
|
12
|
+
File.join(self.class.source_root, "operation.rb"),
|
13
|
+
File.join(options[:path], "#{file_name}.rb")
|
14
|
+
)
|
15
|
+
template(
|
16
|
+
File.join(self.class.source_root, "operation_test.rb"),
|
17
|
+
File.join("test/", options[:path].gsub(/\Aapp\//, ""), "#{file_name}_test.rb")
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def namespace_name
|
24
|
+
namespace_path = options[:path].gsub(/^app\/[^\/]*\//, "")
|
25
|
+
namespace_path.split("/").map(&:camelize).join("::")
|
26
|
+
end
|
27
|
+
end
|
data/lib/typed_operation/base.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "vident/typed"
|
4
4
|
require "vident/typed/attributes"
|
5
5
|
|
6
6
|
module TypedOperation
|
7
7
|
class Base
|
8
|
-
include Dry::Monads[:result, :do]
|
9
8
|
include Vident::Typed::Attributes
|
10
9
|
|
11
10
|
class << self
|
@@ -34,7 +33,11 @@ module TypedOperation
|
|
34
33
|
end
|
35
34
|
|
36
35
|
def initialize(**attributes)
|
37
|
-
|
36
|
+
begin
|
37
|
+
prepare_attributes(attributes)
|
38
|
+
rescue ::Dry::Struct::Error => e
|
39
|
+
raise ParameterError, e.message
|
40
|
+
end
|
38
41
|
prepare if respond_to?(:prepare)
|
39
42
|
end
|
40
43
|
|
@@ -42,10 +45,6 @@ module TypedOperation
|
|
42
45
|
raise NotImplementedError, "You must implement #call"
|
43
46
|
end
|
44
47
|
|
45
|
-
def call!
|
46
|
-
call.value!
|
47
|
-
end
|
48
|
-
|
49
48
|
def to_proc
|
50
49
|
method(:call).to_proc
|
51
50
|
end
|
data/lib/typed_operation.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typed_operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Ierodiaconou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '8.0'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '6.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '8.0'
|
@@ -45,26 +45,21 @@ dependencies:
|
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 0.1.0
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name: dry-
|
48
|
+
name: dry-initializer
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- - "
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '1'
|
54
|
-
- - "<"
|
51
|
+
- - "~>"
|
55
52
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
53
|
+
version: '3.0'
|
57
54
|
type: :runtime
|
58
55
|
prerelease: false
|
59
56
|
version_requirements: !ruby/object:Gem::Requirement
|
60
57
|
requirements:
|
61
|
-
- - "
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: '1'
|
64
|
-
- - "<"
|
58
|
+
- - "~>"
|
65
59
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
67
|
-
description: TypedOperation is a command pattern implementation
|
60
|
+
version: '3.0'
|
61
|
+
description: TypedOperation is a command pattern implementation where inputs can be
|
62
|
+
defined with runtime type checks. Operations can be partially applied.
|
68
63
|
email:
|
69
64
|
- stevegeek@gmail.com
|
70
65
|
executables: []
|
@@ -74,6 +69,13 @@ files:
|
|
74
69
|
- MIT-LICENSE
|
75
70
|
- README.md
|
76
71
|
- Rakefile
|
72
|
+
- lib/generators/USAGE
|
73
|
+
- lib/generators/templates/operation.rb
|
74
|
+
- lib/generators/templates/operation_test.rb
|
75
|
+
- lib/generators/typed_operation/install/USAGE
|
76
|
+
- lib/generators/typed_operation/install/install_generator.rb
|
77
|
+
- lib/generators/typed_operation/install/templates/application_operation.rb
|
78
|
+
- lib/generators/typed_operation_generator.rb
|
77
79
|
- lib/tasks/typed_operation_tasks.rake
|
78
80
|
- lib/typed_operation.rb
|
79
81
|
- lib/typed_operation/base.rb
|