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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53850ead13d940ad019c674a59e7831ba89da9ec70168d6a81de50711f343523
4
- data.tar.gz: e76a1321066eff1a9034aeaab66140d58732eeab7adf30ff8d51f455ce68f483
3
+ metadata.gz: c80a027434c29b23257b43e03eeb8acb61a3ac300a59e0c04068ffada1dd4aa6
4
+ data.tar.gz: 6b78a70b2a46710746129f8dac3a403bdc692c761c93f3ec111bf09efec8a70e
5
5
  SHA512:
6
- metadata.gz: 057de15499ac13647de16cd3905d23ddf390b00d0951449061e1fc30020ba0c2e546d1c1f38495911012177604740f5c3947426c94ee9dd9763f94df9629ae17
7
- data.tar.gz: f73dd9c04f0e5c3f87861c4d086059d595c296cc85783a85d9c13ef03f04ff7f87f46a4ec0b5cb1f9e9123d9f23ee0274a61d89f534ac666ad778db2f592dee0
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
- Results of the operation are a type of `Dry::Monads::Result` object.
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
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/monads"
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
- prepare_attributes(attributes)
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
@@ -1,4 +1,8 @@
1
1
  module TypedOperation
2
2
  class Railtie < ::Rails::Railtie
3
+ generators do
4
+ require "generators/typed_operation/install/install_generator"
5
+ require "generators/typed_operation_generator"
6
+ end
3
7
  end
4
8
  end
@@ -1,3 +1,3 @@
1
1
  module TypedOperation
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -4,7 +4,6 @@ require "typed_operation/base"
4
4
  require "typed_operation/partially_applied"
5
5
  require "typed_operation/prepared"
6
6
 
7
-
8
7
  module TypedOperation
9
- # Your code goes here...
8
+ class ParameterError < StandardError; end
10
9
  end
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.2.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-05-04 00:00:00.000000000 Z
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: '7.0'
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: '7.0'
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-monads
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: '2'
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: '2'
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