pragma-operation 1.6.3 → 2.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.
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
- module Pragma
3
- module Operation
4
- # Provides integration with {https://github.com/pragmarb/pragma-decorator Pragma::Decorator}.
5
- #
6
- # @author Alessandro Desantis
7
- module Decoration
8
- def self.included(base)
9
- base.extend ClassMethods
10
- base.include InstanceMethods
11
- end
12
-
13
- module ClassMethods # :nodoc:
14
- # Sets the decorator to use for decorating this operation.
15
- #
16
- # @param klass [Class] a subclass of +Pragma::Decorator::Base+
17
- #
18
- # @yield A block which will be called with the operation's context which should return
19
- # the decorator class. The block can also return +nil+ if decoration should be skipped.
20
- def decorator(klass = nil, &block)
21
- if !klass && !block_given?
22
- fail ArgumentError, 'You must pass either a decorator class or a block'
23
- end
24
-
25
- @decorator = klass || block
26
- end
27
-
28
- # Returns the decorator class.
29
- #
30
- # @return [Class]
31
- def decorator_klass
32
- @decorator
33
- end
34
- end
35
-
36
- module InstanceMethods # :nodoc:
37
- # Builds the decorator for the given resource, using the previously defined decorator class.
38
- #
39
- # This is just an instance-level alias of {.build_decorator}. You should use this from
40
- # inside the operation.
41
- #
42
- # @param resource [Object]
43
- #
44
- # @return [Pragma::Decorator::Base]
45
- #
46
- # @see #decorate
47
- def build_decorator(resource)
48
- resource = resource.to_a if resource.is_a?(Enumerable)
49
- compute_decorator_klass.represent(resource)
50
- end
51
-
52
- # If a decorator is defined, acts as an alias for {#build_decorator}. If not, simply returns
53
- # the provided resource.
54
- # @param decoratable [Object]
55
- #
56
- # @return [Pragma::Decorator::Base|Object]
57
- #
58
- # @see #build_decorator
59
- def decorate(decoratable)
60
- return decoratable unless compute_decorator_klass
61
- build_decorator(decoratable)
62
- end
63
-
64
- private
65
-
66
- def compute_decorator_klass
67
- if self.class.decorator_klass.is_a?(Proc)
68
- self.class.decorator_klass.call(context)
69
- else
70
- self.class.decorator_klass
71
- end
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,146 +0,0 @@
1
- # frozen_string_literal: true
2
- module Pragma
3
- module Operation
4
- # Provides integration with {https://github.com/pragmarb/pragma-contract Pragma::Contract}.
5
- #
6
- # @author Alessandro Desantis
7
- module Validation
8
- def self.included(base)
9
- base.extend ClassMethods
10
- base.include InstanceMethods
11
- end
12
-
13
- module ClassMethods # :nodoc:
14
- # Sets the contract to use for validating this operation.
15
- #
16
- # @param klass [Class] a subclass of +Pragma::Contract::Base+
17
- #
18
- # @yield A block which will be called with the operation's context which should return
19
- # the contract class. The block can also return +nil+ if validation should be skipped.
20
- def contract(klass = nil, &block)
21
- if !klass && !block_given?
22
- fail ArgumentError, 'You must pass either a contract class or a block'
23
- end
24
-
25
- @contract = klass || block
26
- end
27
-
28
- # Returns the contract class.
29
- #
30
- # @return [Class|Proc]
31
- def contract_klass
32
- @contract
33
- end
34
- end
35
-
36
- module InstanceMethods # :nodoc:
37
- # Builds the contract for the given resource, using the previously defined contract class.
38
- #
39
- # This is just an instance-level alias of {.build_contract}. You should use this from inside
40
- # the operation.
41
- #
42
- # @param resource [Object]
43
- #
44
- # @return [Pragma::Contract::Base]
45
- #
46
- # @see .contract
47
- def build_contract(resource)
48
- contract_klass = compute_contract_klass(resource)
49
- return resource unless contract_klass
50
-
51
- contract_klass.new(resource)
52
- end
53
-
54
- # Validates this operation on the provided contract or resource.
55
- #
56
- # If no contract has been defined for this operation, tries to call +#validate+ on the
57
- # resource. If the resource does not respond to +#validate+, returns true.
58
- #
59
- # @param validatable [Object|Pragma::Contract::Base] contract or resource
60
- #
61
- # @return [Boolean] whether the operation is valid
62
- def validate(validatable)
63
- # rubocop:disable Metrics/LineLength
64
- contract = if Object.const_defined?('Pragma::Contract::Base') && validatable.is_a?(Pragma::Contract::Base)
65
- validatable
66
- else
67
- build_contract(validatable)
68
- end
69
- # rubocop:enable Metrics/LineLength
70
-
71
- if contract.is_a?(Pragma::Contract::Base)
72
- contract.validate(params)
73
- else
74
- contract.respond_to?(:validate) ? contract.validate : true
75
- end.tap do |result|
76
- after_validation(result)
77
- end
78
- end
79
-
80
- # Validates this operation on the provided contract or resource. If the operation is not
81
- # valid, responds with 422 Unprocessable Entity and an error body and halts the execution.
82
- #
83
- # @param validatable [Object|Pragma::Contract::Base] contract or resource
84
- def validate!(validatable)
85
- # rubocop:disable Metrics/LineLength
86
- contract = if Object.const_defined?('Pragma::Contract::Base') && validatable.is_a?(Pragma::Contract::Base)
87
- validatable
88
- else
89
- build_contract(validatable)
90
- end
91
- # rubocop:enable Metrics/LineLength
92
-
93
- respond_with_validation_errors!(contract) unless validate(contract)
94
- end
95
-
96
- # Runs after validation is done.
97
- #
98
- # @param result [Boolean] the result of the validation
99
- def after_validation(result)
100
- end
101
-
102
- # Sets a response suitable for reporting validation errors.
103
- #
104
- # The response will be a 422 Unprocessable Entity, contain the +error_type+, +error_message+
105
- # and +meta+ keys. +meta.errors+ will contain the validation errors.
106
- #
107
- # @param validatable [Object] a validatable object
108
- def respond_with_validation_errors(validatable)
109
- respond_with validation_errors_response(validatable)
110
- end
111
-
112
- # Same as {#respond_with_validation_errors}, but also halts the execution of the operation.
113
- #
114
- # @param validatable [Object] a validatable object
115
- #
116
- # @see #respond_with_validation_errors
117
- def respond_with_validation_errors!(validatable)
118
- respond_with! validation_errors_response(validatable)
119
- end
120
-
121
- private
122
-
123
- def validation_errors_response(validatable)
124
- {
125
- status: :unprocessable_entity,
126
- resource: {
127
- error_type: :contract_not_respected,
128
- error_message: 'The contract for this operation was not respected.',
129
- meta: {
130
- errors: validatable.errors.messages
131
- }
132
- }
133
- }
134
- end
135
-
136
- def compute_contract_klass(_resource)
137
- if self.class.contract_klass.is_a?(Proc)
138
- self.class.contract_klass.call(context)
139
- else
140
- self.class.contract_klass
141
- end
142
- end
143
- end
144
- end
145
- end
146
- end