opera 0.2.17 → 0.3.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: c6b4eeef70ec90ace2eab7861bb9e9801f1e986354a411f2ca426f1380c3a0f7
4
- data.tar.gz: b2264478656ffab0e08ae0e50b7b54a4dffdf81d64bb53bb2a27365151700351
3
+ metadata.gz: 704579e1a9f84d1966d10a7a7dab33b3c51d320a6f44fc968cc41d27e4ddb465
4
+ data.tar.gz: 47cec8209bd334e31fc3906adf6fafabc48fb49438506e1eac3cc63df2739994
5
5
  SHA512:
6
- metadata.gz: efb5db089f99b26ab2f085e62a064dcaf31adc46632fccc9e51ab73f22dc611d9341f7f3ddb5b4d1bdf5d1c8b598aab54af5071df891f0696f5b8357bcd1960b
7
- data.tar.gz: 0c5e84d50fa8f0a0b5f4a839b97e208925420de362ed42ab60e0731aadfe4b7a25462a6927078feb185dd03c2621aa09562a13d5893b3fdba3bd9de171e01fd6
6
+ metadata.gz: b83cebe96114838b10845ae364ca6869b445d4a6a0171deb40875db0a719112a856820ace81929740b1914f52a8c083f24e4fe43e11acf3d8b519135da0a2a6b
7
+ data.tar.gz: 815abc701e8f4634b47c868e9fed8f2b72682eb0fc408efad05afbc9f055f2f2d870c59caf84cafb46993cb5c75e6a2616c67684462fe38828d43b285cfa43e6
@@ -9,7 +9,7 @@ jobs:
9
9
  runs-on: ubuntu-latest
10
10
  strategy:
11
11
  matrix:
12
- ruby-version: [ '2.6', '2.7', '3.0', '3.2', 'jruby' ]
12
+ ruby-version: [ '3.0', '3.2', 'jruby' ]
13
13
 
14
14
  steps:
15
15
  - uses: actions/checkout@v4
@@ -16,7 +16,7 @@ jobs:
16
16
  runs-on: ubuntu-latest
17
17
  strategy:
18
18
  matrix:
19
- ruby-version: ['2.6', '2.7', '3.0', '3.2', 'jruby']
19
+ ruby-version: ['3.0', '3.2', 'jruby']
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Opera Changelog
2
2
 
3
+ ### 0.3.0 - September 20, 2024
4
+
5
+ - add new syntax for context, params and dependencies readers and accessors
6
+
7
+ ### 0.2.18 - September 20, 2024
8
+
9
+ - added `output!` method on Result object
10
+ - deleted `to_h` alias for `output`
11
+
3
12
  ### 0.2.17 - July 8, 2024
4
13
 
5
14
  - minor fix `mode` configuration option.
data/Gemfile.lock CHANGED
@@ -1,74 +1,71 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- opera (0.2.16)
4
+ opera (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ bigdecimal (3.1.8)
9
10
  byebug (11.1.3)
10
11
  coderay (1.1.3)
11
- concurrent-ruby (1.1.7)
12
- diff-lcs (1.4.4)
13
- dry-configurable (0.11.6)
12
+ concurrent-ruby (1.3.4)
13
+ diff-lcs (1.5.1)
14
+ dry-configurable (1.2.0)
15
+ dry-core (~> 1.0, < 2)
16
+ zeitwerk (~> 2.6)
17
+ dry-core (1.0.1)
14
18
  concurrent-ruby (~> 1.0)
15
- dry-core (~> 0.4, >= 0.4.7)
16
- dry-equalizer (~> 0.2)
17
- dry-container (0.7.2)
19
+ zeitwerk (~> 2.6)
20
+ dry-inflector (1.1.0)
21
+ dry-initializer (3.1.1)
22
+ dry-logic (1.5.0)
18
23
  concurrent-ruby (~> 1.0)
19
- dry-configurable (~> 0.1, >= 0.1.3)
20
- dry-core (0.5.0)
24
+ dry-core (~> 1.0, < 2)
25
+ zeitwerk (~> 2.6)
26
+ dry-schema (1.13.4)
21
27
  concurrent-ruby (~> 1.0)
22
- dry-equalizer (0.3.0)
23
- dry-inflector (0.2.0)
24
- dry-initializer (3.0.4)
25
- dry-logic (1.0.8)
26
- concurrent-ruby (~> 1.0)
27
- dry-core (~> 0.2)
28
- dry-equalizer (~> 0.2)
29
- dry-schema (1.5.6)
30
- concurrent-ruby (~> 1.0)
31
- dry-configurable (~> 0.8, >= 0.8.3)
32
- dry-core (~> 0.4)
33
- dry-equalizer (~> 0.2)
28
+ dry-configurable (~> 1.0, >= 1.0.1)
29
+ dry-core (~> 1.0, < 2)
34
30
  dry-initializer (~> 3.0)
35
- dry-logic (~> 1.0)
36
- dry-types (~> 1.4)
37
- dry-types (1.4.0)
31
+ dry-logic (>= 1.4, < 2)
32
+ dry-types (>= 1.7, < 2)
33
+ zeitwerk (~> 2.6)
34
+ dry-types (1.7.2)
35
+ bigdecimal (~> 3.0)
38
36
  concurrent-ruby (~> 1.0)
39
- dry-container (~> 0.3)
40
- dry-core (~> 0.4, >= 0.4.4)
41
- dry-equalizer (~> 0.3)
42
- dry-inflector (~> 0.1, >= 0.1.2)
43
- dry-logic (~> 1.0, >= 1.0.2)
44
- dry-validation (1.6.0)
37
+ dry-core (~> 1.0)
38
+ dry-inflector (~> 1.0)
39
+ dry-logic (~> 1.4)
40
+ zeitwerk (~> 2.6)
41
+ dry-validation (1.10.0)
45
42
  concurrent-ruby (~> 1.0)
46
- dry-container (~> 0.7, >= 0.7.1)
47
- dry-core (~> 0.4)
48
- dry-equalizer (~> 0.2)
43
+ dry-core (~> 1.0, < 2)
49
44
  dry-initializer (~> 3.0)
50
- dry-schema (~> 1.5, >= 1.5.2)
51
- method_source (1.0.0)
52
- pry (0.13.1)
45
+ dry-schema (>= 1.12, < 2)
46
+ zeitwerk (~> 2.6)
47
+ method_source (1.1.0)
48
+ pry (0.14.2)
53
49
  coderay (~> 1.1)
54
50
  method_source (~> 1.0)
55
- pry-byebug (3.9.0)
51
+ pry-byebug (3.10.1)
56
52
  byebug (~> 11.0)
57
- pry (~> 0.13.0)
53
+ pry (>= 0.13, < 0.15)
58
54
  rake (12.3.3)
59
- rspec (3.9.0)
60
- rspec-core (~> 3.9.0)
61
- rspec-expectations (~> 3.9.0)
62
- rspec-mocks (~> 3.9.0)
63
- rspec-core (3.9.2)
64
- rspec-support (~> 3.9.3)
65
- rspec-expectations (3.9.2)
55
+ rspec (3.13.0)
56
+ rspec-core (~> 3.13.0)
57
+ rspec-expectations (~> 3.13.0)
58
+ rspec-mocks (~> 3.13.0)
59
+ rspec-core (3.13.1)
60
+ rspec-support (~> 3.13.0)
61
+ rspec-expectations (3.13.3)
66
62
  diff-lcs (>= 1.2.0, < 2.0)
67
- rspec-support (~> 3.9.0)
68
- rspec-mocks (3.9.1)
63
+ rspec-support (~> 3.13.0)
64
+ rspec-mocks (3.13.1)
69
65
  diff-lcs (>= 1.2.0, < 2.0)
70
- rspec-support (~> 3.9.0)
71
- rspec-support (3.9.3)
66
+ rspec-support (~> 3.13.0)
67
+ rspec-support (3.13.1)
68
+ zeitwerk (2.6.18)
72
69
 
73
70
  PLATFORMS
74
71
  ruby
data/README.md CHANGED
@@ -26,6 +26,8 @@ Or install it yourself as:
26
26
 
27
27
  $ gem install opera
28
28
 
29
+ Note. If you are using Ruby 2.x please use Opera 0.2.x
30
+
29
31
  ## Configuration
30
32
 
31
33
  Opera is built to be used with or without Rails.
@@ -159,8 +161,16 @@ Some cases and example how to use new operations
159
161
 
160
162
  ```ruby
161
163
  class Profile::Create < Opera::Operation::Base
162
- context_accessor :profile
163
- dependencies_reader :current_account, :mailer
164
+ # DEPRECATED
165
+ # context_accessor :profile
166
+ context do
167
+ attr_accessor :profile
168
+ end
169
+ # DEPRECATED
170
+ # dependencies_reader :current_account, :mailer
171
+ dependencies do
172
+ attr_reader :current_account, :mailer
173
+ end
164
174
 
165
175
  validate :profile_schema
166
176
 
@@ -232,8 +242,17 @@ Profile::Create.call(params: {
232
242
 
233
243
  ```ruby
234
244
  class Profile::Create < Opera::Operation::Base
235
- context_accessor :profile
236
- dependencies_reader :current_account, :mailer
245
+ # DEPRECATED
246
+ # context_accessor :profile
247
+ context do
248
+ attr_accessor :profile
249
+ end
250
+ # DEPRECATED
251
+ # dependencies_reader :current_account, :mailer
252
+ dependencies do
253
+ attr_reader :current_account, :mailer
254
+ end
255
+
237
256
 
238
257
  validate :profile_schema
239
258
 
@@ -282,8 +301,16 @@ Profile::Create.call(params: {
282
301
 
283
302
  ```ruby
284
303
  class Profile::Create < Opera::Operation::Base
285
- context_accessor :profile
286
- dependencies_reader :current_account, :mailer
304
+ # DEPRECATED
305
+ # context_accessor :profile
306
+ context do
307
+ attr_accessor :profile
308
+ end
309
+ # DEPRECATED
310
+ # dependencies_reader :current_account, :mailer
311
+ dependencies do
312
+ attr_reader :current_account, :mailer
313
+ end
287
314
 
288
315
  validate :profile_schema
289
316
 
@@ -358,8 +385,16 @@ Profile::Create.call(params: {
358
385
 
359
386
  ```ruby
360
387
  class Profile::Create < Opera::Operation::Base
361
- context_accessor :profile
362
- dependencies_reader :current_account, :mailer
388
+ # DEPRECATED
389
+ # context_accessor :profile
390
+ context do
391
+ attr_accessor :profile
392
+ end
393
+ # DEPRECATED
394
+ # dependencies_reader :current_account, :mailer
395
+ dependencies do
396
+ attr_reader :current_account, :mailer
397
+ end
363
398
 
364
399
  validate :profile_schema
365
400
 
@@ -417,8 +452,16 @@ result = Profile::Create.call(params: {
417
452
 
418
453
  ```ruby
419
454
  class Profile::Create < Opera::Operation::Base
420
- context_accessor :profile
421
- dependencies_reader :current_account, :mailer
455
+ # DEPRECATED
456
+ # context_accessor :profile
457
+ context do
458
+ attr_accessor :profile
459
+ end
460
+ # DEPRECATED
461
+ # dependencies_reader :current_account, :mailer
462
+ dependencies do
463
+ attr_reader :current_account, :mailer
464
+ end
422
465
 
423
466
  validate :profile_schema
424
467
 
@@ -476,8 +519,16 @@ class Profile::Create < Opera::Operation::Base
476
519
  config.transaction_class = Profile
477
520
  end
478
521
 
479
- context_accessor :profile
480
- dependencies_reader :current_account, :mailer
522
+ # DEPRECATED
523
+ # context_accessor :profile
524
+ context do
525
+ attr_accessor :profile
526
+ end
527
+ # DEPRECATED
528
+ # dependencies_reader :current_account, :mailer
529
+ dependencies do
530
+ attr_reader :current_account, :mailer
531
+ end
481
532
 
482
533
  validate :profile_schema
483
534
 
@@ -541,8 +592,16 @@ class Profile::Create < Opera::Operation::Base
541
592
  config.transaction_class = Profile
542
593
  end
543
594
 
544
- context_accessor :profile
545
- dependencies_reader :current_account, :mailer
595
+ # DEPRECATED
596
+ # context_accessor :profile
597
+ context do
598
+ attr_accessor :profile
599
+ end
600
+ # DEPRECATED
601
+ # dependencies_reader :current_account, :mailer
602
+ dependencies do
603
+ attr_reader :current_account, :mailer
604
+ end
546
605
 
547
606
  validate :profile_schema
548
607
 
@@ -602,8 +661,16 @@ D, [2020-08-17T12:10:44.898132 #2741] DEBUG -- : (10.3ms) COMMIT
602
661
 
603
662
  ```ruby
604
663
  class Profile::Create < Opera::Operation::Base
605
- context_accessor :profile
606
- dependencies_reader :current_account, :mailer
664
+ # DEPRECATED
665
+ # context_accessor :profile
666
+ context do
667
+ attr_accessor :profile
668
+ end
669
+ # DEPRECATED
670
+ # dependencies_reader :current_account, :mailer
671
+ dependencies do
672
+ attr_reader :current_account, :mailer
673
+ end
607
674
 
608
675
  validate :profile_schema
609
676
 
@@ -657,8 +724,16 @@ Profile::Create.call(params: {
657
724
 
658
725
  ```ruby
659
726
  class Profile::Create < Opera::Operation::Base
660
- context_accessor :profile
661
- dependencies_reader :current_account, :mailer
727
+ # DEPRECATED
728
+ # context_accessor :profile
729
+ context do
730
+ attr_accessor :profile
731
+ end
732
+ # DEPRECATED
733
+ # dependencies_reader :current_account, :mailer
734
+ dependencies do
735
+ attr_reader :current_account, :mailer
736
+ end
662
737
 
663
738
  validate :profile_schema
664
739
 
@@ -719,8 +794,16 @@ Profile::Create.call(params: {
719
794
 
720
795
  ```ruby
721
796
  class Profile::Create < Opera::Operation::Base
722
- context_accessor :profile
723
- dependencies_reader :current_account, :mailer
797
+ # DEPRECATED
798
+ # context_accessor :profile
799
+ context do
800
+ attr_accessor :profile
801
+ end
802
+ # DEPRECATED
803
+ # dependencies_reader :current_account, :mailer
804
+ dependencies do
805
+ attr_reader :current_account, :mailer
806
+ end
724
807
 
725
808
  validate :profile_schema
726
809
 
@@ -880,6 +963,7 @@ Opera::Operation::Result.new(output: 'success')
880
963
  - failure? - [true, false] - Return true if any error or exception
881
964
  - output - [Anything] - Return Anything
882
965
  - output=(Anything) - Sets content of operation output
966
+ - output! - Return Anything if Success, raise exception if Failure
883
967
  - add_error(key, value) - Adds new error message
884
968
  - add_errors(Hash) - Adds multiple error messages
885
969
  - add_exception(method, message, classname: nil) - Adds new exception
@@ -976,26 +1060,11 @@ end
976
1060
 
977
1061
  For creating instance methods that are meant to be read-only and not stored within a context hash, defining these methods as private is a more suitable and clear approach compared to using context_reader with a default. This method ensures that transient dependencies remain well-encapsulated and are not confused with persistent application state.
978
1062
 
979
- #### `context_writer`
1063
+ ### `context|params|depenencies`
980
1064
 
981
- The `context_writer` helper method is designed to enable setting of values for specified keys within a `context` hash. This method dynamically defines a method that acts as a setter, allowing for the direct modification of the value associated with a given key.
982
-
983
- #### Usage
984
- ```ruby
985
- context_writer :profile
1065
+ The `context|params|depenencies` helper method is designed to enable easy access to and modification of values for specified keys within a `context` hash. This method dynamically defines both getter and setter methods for the designated keys, facilitating straightforward retrieval and update of values.
986
1066
 
987
- step :fetch_profile
988
-
989
- def fetch_profile
990
- self.profile = ProfileFetcher.call # sets context[:profile]
991
- end
992
- ```
993
-
994
- #### `context_accessor`
995
-
996
- The `context_accessor` helper method is designed to enable easy access to and modification of values for specified keys within a `context` hash. This method dynamically defines both getter and setter methods for the designated keys, facilitating straightforward retrieval and update of values.
997
-
998
- #### Parameters
1067
+ #### attr_reader, attr_accessor Parameters
999
1068
 
1000
1069
  **key (Symbol):** The key(s) for which the getter and setter methods are to be created. These symbols will correspond to keys in the context hash.
1001
1070
 
@@ -1003,7 +1072,9 @@ The `context_accessor` helper method is designed to enable easy access to and mo
1003
1072
 
1004
1073
  #### Usage
1005
1074
  ```ruby
1006
- context_accessor :profile
1075
+ context do
1076
+ attr_accessor :profile
1077
+ end
1007
1078
 
1008
1079
  step :fetch_profile
1009
1080
  step :update_profile
@@ -1018,16 +1089,19 @@ end
1018
1089
  ```
1019
1090
 
1020
1091
  ```ruby
1021
- context_accessor :profile, default: -> { Profile.new }
1092
+ context do
1093
+ attr_accessor :profile, default: -> { Profile.new }
1094
+ end
1022
1095
  ```
1023
1096
 
1024
1097
  ```ruby
1025
- context_accessor :profile, :account
1098
+ context do
1099
+ attr_accessor :profile, :account
1100
+ end
1026
1101
  ```
1027
1102
 
1028
1103
  #### Other methods
1029
1104
  >
1030
- - [params|dependencies]_reader - predefined readers for immutable arguments
1031
1105
  - step(Symbol) - single instruction
1032
1106
  - return [Truthly] - continue operation execution
1033
1107
  - return [False] - stops operation execution
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Opera
4
+ module Operation
5
+ class AttributesDSL
6
+ attr_accessor :klass, :block_name, :allowed
7
+
8
+ def initialize(klass:, block_name:, allowed: [:attr_reader])
9
+ @klass = klass
10
+ @allowed = allowed
11
+ @block_name = block_name
12
+ end
13
+
14
+ def attr_reader(*attributes, **options)
15
+ raise NoMethodError, "You cannot use attr_reader inside #{klass.name}##{block_name}" unless allowed.include?(:attr_reader)
16
+
17
+ attributes.each do |attribute|
18
+ klass.check_method_availability!(attribute)
19
+
20
+ method = block_name
21
+ klass.define_method(attribute) do
22
+ value = if send(method).key?(attribute)
23
+ send(method)[attribute]
24
+ elsif options[:default]
25
+ instance_exec(&options[:default])
26
+ end
27
+
28
+ if send(method).frozen?
29
+ send(method)[attribute] || value
30
+ else
31
+ send(method)[attribute] ||= value
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def attr_writer(*attributes, **options)
38
+ raise NoMethodError, "You cannot use attr_writer inside #{klass.name}##{block_name}" unless allowed.include?(:attr_accessor)
39
+
40
+ attributes.each do |attribute|
41
+ klass.check_method_availability!("#{attribute}=")
42
+ method = block_name
43
+ klass.define_method("#{attribute}=") do |value|
44
+ send(method)[attribute] = value
45
+ end
46
+ end
47
+ end
48
+
49
+ def attr_accessor(*attributes, **options)
50
+ raise NoMethodError, "You cannot use attr_accessor inside #{klass.name}##{block_name}" unless allowed.include?(:attr_accessor)
51
+
52
+ attr_reader(*attributes, **options)
53
+ attr_writer(*attributes)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -55,42 +55,39 @@ module Opera
55
55
  raise(ArgumentError, "Method #{method} is already defined")
56
56
  end
57
57
 
58
+ def context(&blk)
59
+ AttributesDSL.new(klass: self, block_name: :context, allowed: [:attr_reader, :attr_accessor]).instance_exec(&blk)
60
+ end
61
+
62
+ def params(&blk)
63
+ AttributesDSL.new(klass: self, block_name: :params).instance_exec(&blk)
64
+ end
65
+
66
+ def dependencies(&blk)
67
+ AttributesDSL.new(klass: self, block_name: :dependencies).instance_exec(&blk)
68
+ end
69
+
70
+ # TODO: Delete with newer version
58
71
  %i[context params dependencies].each do |method|
59
72
  define_method("#{method}_reader") do |*attributes, **options|
60
- attributes.map(&:to_sym).each do |attribute|
61
- check_method_availability!(attribute)
62
-
63
- define_method(attribute) do
64
- value = if send(method).key?(attribute)
65
- send(method)[attribute]
66
- elsif options[:default]
67
- instance_exec(&options[:default])
68
- end
69
-
70
- if send(method).frozen?
71
- send(method)[attribute] || value
72
- else
73
- send(method)[attribute] ||= value
74
- end
75
- end
73
+ send(method) do
74
+ attr_reader *attributes, **options
76
75
  end
77
76
  end
78
77
  end
79
78
 
80
79
  %i[context].each do |method|
81
80
  define_method("#{method}_writer") do |*attributes|
82
- attributes.map(&:to_sym).each do |attribute|
83
- check_method_availability!("#{attribute}=")
84
-
85
- define_method("#{attribute}=") do |value|
86
- send(method)[attribute] = value
87
- end
81
+ send(method) do
82
+ attr_writer *attributes
88
83
  end
89
84
  end
90
85
 
91
86
  define_method("#{method}_accessor") do |*attributes, **options|
92
- send("#{method}_reader", *attributes, **options)
93
- send("#{method}_writer", *attributes)
87
+ send(method) do
88
+ attr_reader *attributes, **options
89
+ attr_writer *attributes, **options
90
+ end
94
91
  end
95
92
  end
96
93
  end
@@ -17,7 +17,7 @@ module Opera
17
17
 
18
18
  case dry_result
19
19
  when Opera::Operation::Result
20
- add_instruction_output(instruction, dry_result.to_h)
20
+ add_instruction_output(instruction, dry_result.output)
21
21
 
22
22
  unless dry_result.success?
23
23
  result.add_errors(dry_result.errors)
@@ -3,14 +3,14 @@
3
3
  module Opera
4
4
  module Operation
5
5
  class Result
6
+ class OutputError < StandardError; end
7
+
6
8
  attr_reader :errors, # Acumulator of errors in validation + steps
7
9
  :exceptions, # Acumulator of exceptions in steps
8
10
  :information, # Temporal object to store related information
9
11
  :executions # Stacktrace or Pipe of the methods evaludated
10
12
 
11
- attr_accessor :output # Final object returned if success?
12
-
13
- alias to_h output
13
+ attr_accessor :output # in case of success, it contains the resulting value
14
14
 
15
15
  def initialize(output: nil, errors: {})
16
16
  @errors = errors
@@ -32,6 +32,12 @@ module Opera
32
32
  errors.merge(exceptions)
33
33
  end
34
34
 
35
+ def output!
36
+ raise OutputError, 'Cannot retrieve output from a Failure.' if failure?
37
+
38
+ output
39
+ end
40
+
35
41
  # rubocop:disable Metrics/MethodLength
36
42
  def add_error(field, message)
37
43
  @errors[field] ||= []
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'opera/operation/attributes_dsl'
3
4
  require 'opera/operation/builder'
4
5
  require 'opera/operation/base'
5
6
  require 'opera/operation/executor'
data/lib/opera/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Opera
4
- VERSION = '0.2.17'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opera
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.17
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ProFinda Development Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-08 00:00:00.000000000 Z
11
+ date: 2024-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -78,6 +78,7 @@ files:
78
78
  - lib/opera.rb
79
79
  - lib/opera/errors.rb
80
80
  - lib/opera/operation.rb
81
+ - lib/opera/operation/attributes_dsl.rb
81
82
  - lib/opera/operation/base.rb
82
83
  - lib/opera/operation/builder.rb
83
84
  - lib/opera/operation/config.rb