pragma-operation 1.6.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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