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.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -8
- data/README.md +164 -3
- data/lib/pragma/operation.rb +14 -4
- data/lib/pragma/operation/base.rb +2 -247
- data/lib/pragma/operation/error.rb +27 -0
- data/lib/pragma/operation/response.rb +102 -0
- data/lib/pragma/operation/response/bad_request.rb +16 -0
- data/lib/pragma/operation/response/created.rb +13 -0
- data/lib/pragma/operation/response/forbidden.rb +19 -0
- data/lib/pragma/operation/response/no_content.rb +13 -0
- data/lib/pragma/operation/response/not_found.rb +19 -0
- data/lib/pragma/operation/response/ok.rb +13 -0
- data/lib/pragma/operation/response/unprocessable_entity.rb +23 -0
- data/lib/pragma/operation/version.rb +2 -1
- data/pragma-operation.gemspec +16 -19
- metadata +15 -55
- data/doc/01-basic-usage.md +0 -264
- data/doc/02-contracts.md +0 -154
- data/doc/03-policies.md +0 -179
- data/doc/04-decorators.md +0 -50
- data/lib/pragma/operation/authorization.rb +0 -130
- data/lib/pragma/operation/decoration.rb +0 -76
- data/lib/pragma/operation/validation.rb +0 -146
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pragma
|
4
|
+
module Operation
|
5
|
+
class Error
|
6
|
+
attr_reader :error_type, :error_message, :meta
|
7
|
+
|
8
|
+
def initialize(error_type:, error_message:, meta: {})
|
9
|
+
@error_type = error_type
|
10
|
+
@error_message = error_message
|
11
|
+
@meta = meta
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_json
|
15
|
+
{
|
16
|
+
error_type: error_type,
|
17
|
+
error_message: error_message,
|
18
|
+
meta: meta
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json
|
23
|
+
JSON.dump as_json
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pragma
|
4
|
+
module Operation
|
5
|
+
class Response
|
6
|
+
STATUSES = {
|
7
|
+
100 => :continue,
|
8
|
+
101 => :switching_protocols,
|
9
|
+
102 => :processing,
|
10
|
+
200 => :ok,
|
11
|
+
201 => :created,
|
12
|
+
202 => :accepted,
|
13
|
+
203 => :non_authoritative_information,
|
14
|
+
204 => :no_content,
|
15
|
+
205 => :reset_content,
|
16
|
+
206 => :partial_content,
|
17
|
+
207 => :multi_status,
|
18
|
+
208 => :already_reported,
|
19
|
+
300 => :multiple_choices,
|
20
|
+
301 => :moved_permanently,
|
21
|
+
302 => :found,
|
22
|
+
303 => :see_other,
|
23
|
+
304 => :not_modified,
|
24
|
+
305 => :use_proxy,
|
25
|
+
307 => :temporary_redirect,
|
26
|
+
400 => :bad_request,
|
27
|
+
401 => :unauthorized,
|
28
|
+
402 => :payment_required,
|
29
|
+
403 => :forbidden,
|
30
|
+
404 => :not_found,
|
31
|
+
405 => :method_not_allowed,
|
32
|
+
406 => :not_acceptable,
|
33
|
+
407 => :proxy_authentication_required,
|
34
|
+
408 => :request_timeout,
|
35
|
+
409 => :conflict,
|
36
|
+
410 => :gone,
|
37
|
+
411 => :length_required,
|
38
|
+
412 => :precondition_failed,
|
39
|
+
413 => :request_entity_too_large,
|
40
|
+
414 => :request_uri_too_large,
|
41
|
+
415 => :unsupported_media_type,
|
42
|
+
416 => :request_range_not_satisfiable,
|
43
|
+
417 => :expectation_failed,
|
44
|
+
418 => :im_a_teapot,
|
45
|
+
422 => :unprocessable_entity,
|
46
|
+
423 => :locked,
|
47
|
+
424 => :failed_dependency,
|
48
|
+
425 => :unordered_collection,
|
49
|
+
426 => :upgrade_required,
|
50
|
+
428 => :precondition_required,
|
51
|
+
429 => :too_many_requests,
|
52
|
+
431 => :request_header_fields_too_large,
|
53
|
+
449 => :retry_with,
|
54
|
+
500 => :internal_server_error,
|
55
|
+
501 => :not_implemented,
|
56
|
+
502 => :bad_gateway,
|
57
|
+
503 => :service_unavailable,
|
58
|
+
504 => :gateway_timeout,
|
59
|
+
505 => :http_version_not_supported,
|
60
|
+
506 => :variant_also_negotiates,
|
61
|
+
507 => :insufficient_storage,
|
62
|
+
509 => :bandwidth_limit_exceeded,
|
63
|
+
510 => :not_extended,
|
64
|
+
511 => :network_authentication_required
|
65
|
+
}.freeze
|
66
|
+
|
67
|
+
attr_accessor :entity, :headers
|
68
|
+
attr_reader :status
|
69
|
+
|
70
|
+
def initialize(status: 200, entity: nil, headers: {})
|
71
|
+
self.status = status
|
72
|
+
self.entity = entity
|
73
|
+
self.headers = headers
|
74
|
+
end
|
75
|
+
|
76
|
+
def success?
|
77
|
+
%w[1 2 3].include?(@status.to_s[0])
|
78
|
+
end
|
79
|
+
|
80
|
+
def failure?
|
81
|
+
!success?
|
82
|
+
end
|
83
|
+
|
84
|
+
def status=(v)
|
85
|
+
case v
|
86
|
+
when Integer
|
87
|
+
fail ArgumentError, "#{v} is not a valid status code" unless STATUSES[v]
|
88
|
+
@status = v
|
89
|
+
when Symbol, String
|
90
|
+
fail ArgumentError, "#{v} is not a valid status phrase" unless STATUSES.invert[v.to_sym]
|
91
|
+
@status = STATUSES.invert[v.to_sym]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def decorate_with(decorator)
|
96
|
+
tap do
|
97
|
+
self.entity = decorator.represent(entity)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pragma
|
4
|
+
module Operation
|
5
|
+
class Response
|
6
|
+
class BadRequest < Response
|
7
|
+
def initialize(
|
8
|
+
entity: Error.new(error_type: :bad_request, error_message: 'This request is malformed.'),
|
9
|
+
headers: {}
|
10
|
+
)
|
11
|
+
super(status: 400, entity: entity, headers: headers)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pragma
|
4
|
+
module Operation
|
5
|
+
class Response
|
6
|
+
class Forbidden < Response
|
7
|
+
def initialize(
|
8
|
+
entity: Error.new(
|
9
|
+
error_type: :forbidden,
|
10
|
+
error_message: 'You are not authorized to access the requested resource.'
|
11
|
+
),
|
12
|
+
headers: {}
|
13
|
+
)
|
14
|
+
super(status: 403, entity: entity, headers: headers)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pragma
|
4
|
+
module Operation
|
5
|
+
class Response
|
6
|
+
class NotFound < Response
|
7
|
+
def initialize(
|
8
|
+
entity: Error.new(
|
9
|
+
error_type: :not_found,
|
10
|
+
error_message: 'The requested resource could not be found.'
|
11
|
+
),
|
12
|
+
headers: {}
|
13
|
+
)
|
14
|
+
super(status: 404, entity: entity, headers: headers)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pragma
|
4
|
+
module Operation
|
5
|
+
class Response
|
6
|
+
class UnprocessableEntity < Response
|
7
|
+
def initialize(entity: nil, headers: {}, errors: nil)
|
8
|
+
fail ArgumentError, 'You cannot provide both :entity and :errors!' if entity && errors
|
9
|
+
|
10
|
+
entity ||= Error.new(
|
11
|
+
error_type: :unprocessable_entity,
|
12
|
+
error_message: 'The provided resource is in an unexpected format.',
|
13
|
+
meta: {
|
14
|
+
errors: errors || {}
|
15
|
+
}
|
16
|
+
)
|
17
|
+
|
18
|
+
super(status: 422, entity: entity, headers: headers)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/pragma-operation.gemspec
CHANGED
@@ -1,35 +1,32 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'pragma/operation/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'pragma-operation'
|
8
9
|
spec.version = Pragma::Operation::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
10
|
+
spec.authors = ['Alessandro Desantis']
|
11
|
+
spec.email = ['desa.alessandro@gmail.com']
|
11
12
|
|
12
13
|
spec.summary = 'Business logic encapsulation for your JSON API.'
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
14
|
+
spec.homepage = 'https://github.com/pragmarb/pragma-operation'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
18
|
f.match(%r{^(test|spec|features)/})
|
18
19
|
end
|
19
|
-
spec.bindir =
|
20
|
+
spec.bindir = 'exe'
|
20
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
-
spec.require_paths = [
|
22
|
-
|
23
|
-
spec.add_dependency 'interactor', '~> 3.1.0'
|
22
|
+
spec.require_paths = ['lib']
|
24
23
|
|
25
|
-
spec.
|
26
|
-
spec.add_development_dependency 'pragma-contract', '~> 0.1.0'
|
27
|
-
spec.add_development_dependency 'pragma-decorator', '~> 0.1.0'
|
24
|
+
spec.add_dependency 'trailblazer-operation', '~> 0.0'
|
28
25
|
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
26
|
+
spec.add_development_dependency 'bundler'
|
27
|
+
spec.add_development_dependency 'rake'
|
28
|
+
spec.add_development_dependency 'rspec'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
30
|
+
spec.add_development_dependency 'rubocop-rspec'
|
31
|
+
spec.add_development_dependency 'coveralls'
|
35
32
|
end
|
metadata
CHANGED
@@ -1,71 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pragma-operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Desantis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: trailblazer-operation
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: pragma-policy
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.1.0
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 0.1.0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: pragma-contract
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.0
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1.0
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: pragma-decorator
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.1.0
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 0.1.0
|
26
|
+
version: '0.0'
|
69
27
|
- !ruby/object:Gem::Dependency
|
70
28
|
name: bundler
|
71
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,15 +125,17 @@ files:
|
|
167
125
|
- Rakefile
|
168
126
|
- bin/console
|
169
127
|
- bin/setup
|
170
|
-
- doc/01-basic-usage.md
|
171
|
-
- doc/02-contracts.md
|
172
|
-
- doc/03-policies.md
|
173
|
-
- doc/04-decorators.md
|
174
128
|
- lib/pragma/operation.rb
|
175
|
-
- lib/pragma/operation/authorization.rb
|
176
129
|
- lib/pragma/operation/base.rb
|
177
|
-
- lib/pragma/operation/
|
178
|
-
- lib/pragma/operation/
|
130
|
+
- lib/pragma/operation/error.rb
|
131
|
+
- lib/pragma/operation/response.rb
|
132
|
+
- lib/pragma/operation/response/bad_request.rb
|
133
|
+
- lib/pragma/operation/response/created.rb
|
134
|
+
- lib/pragma/operation/response/forbidden.rb
|
135
|
+
- lib/pragma/operation/response/no_content.rb
|
136
|
+
- lib/pragma/operation/response/not_found.rb
|
137
|
+
- lib/pragma/operation/response/ok.rb
|
138
|
+
- lib/pragma/operation/response/unprocessable_entity.rb
|
179
139
|
- lib/pragma/operation/version.rb
|
180
140
|
- pragma-operation.gemspec
|
181
141
|
homepage: https://github.com/pragmarb/pragma-operation
|
@@ -198,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
158
|
version: '0'
|
199
159
|
requirements: []
|
200
160
|
rubyforge_project:
|
201
|
-
rubygems_version: 2.6.
|
161
|
+
rubygems_version: 2.6.13
|
202
162
|
signing_key:
|
203
163
|
specification_version: 4
|
204
164
|
summary: Business logic encapsulation for your JSON API.
|
data/doc/01-basic-usage.md
DELETED
@@ -1,264 +0,0 @@
|
|
1
|
-
# Basic usage
|
2
|
-
|
3
|
-
Here's the simplest operation you can write:
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
module API
|
7
|
-
module V1
|
8
|
-
module Ping
|
9
|
-
module Operation
|
10
|
-
class Create < Pragma::Operation::Base
|
11
|
-
def call
|
12
|
-
# The `status` parameter is optional (the default is `:ok`).
|
13
|
-
respond_with(
|
14
|
-
status: :ok,
|
15
|
-
resource: { pong: params[:pong] }
|
16
|
-
)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
```
|
24
|
-
|
25
|
-
Here's how you use it:
|
26
|
-
|
27
|
-
```ruby
|
28
|
-
result = API::V1::Ping::Operation::Create.call(params: { pong: 'HELLO' })
|
29
|
-
|
30
|
-
result.status # => :ok
|
31
|
-
result.resource # => { pong: 'HELLO' }
|
32
|
-
```
|
33
|
-
|
34
|
-
As you can see, an operation takes parameters as input and responds with:
|
35
|
-
|
36
|
-
- an HTTP status code;
|
37
|
-
- (optional) a resource (i.e. an object implementing `#to_json`).
|
38
|
-
|
39
|
-
If you don't want to return a resource, you can use the `#head` shortcut:
|
40
|
-
|
41
|
-
```ruby
|
42
|
-
module API
|
43
|
-
module V1
|
44
|
-
module Ping
|
45
|
-
module Operation
|
46
|
-
class Create < Pragma::Operation::Base
|
47
|
-
def call
|
48
|
-
head :no_content
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
Since Pragma::Operation is built on top of [Interactor](https://github.com/collectiveidea/interactor),
|
58
|
-
you should consult its documentation for the basic usage of operations; the rest of this section
|
59
|
-
only covers the features provided specifically by Pragma::Operation.
|
60
|
-
|
61
|
-
## Headers
|
62
|
-
|
63
|
-
You can attach headers to your response by manipulating the `headers` hash:
|
64
|
-
|
65
|
-
```ruby
|
66
|
-
module API
|
67
|
-
module V1
|
68
|
-
module Post
|
69
|
-
module Operation
|
70
|
-
class Create < Pragma::Operation::Base
|
71
|
-
def call
|
72
|
-
post = ::Post.new(params)
|
73
|
-
post.save!
|
74
|
-
|
75
|
-
headers['X-Post-Id'] = post.id
|
76
|
-
|
77
|
-
respond_with status: :created, resource: post
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
```
|
85
|
-
|
86
|
-
You can also set headers when calling `#respond_with`:
|
87
|
-
|
88
|
-
```ruby
|
89
|
-
module API
|
90
|
-
module V1
|
91
|
-
module Post
|
92
|
-
module Operation
|
93
|
-
class Create < Pragma::Operation::Base
|
94
|
-
def call
|
95
|
-
post = ::Post.new(params)
|
96
|
-
post.save!
|
97
|
-
|
98
|
-
respond_with status: :created, resource: post, headers: {
|
99
|
-
'X-Post-Id' => post.id
|
100
|
-
}
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
```
|
108
|
-
|
109
|
-
## HATEOAS
|
110
|
-
|
111
|
-
Pragma::Operation supports HATEOAS by allowing you to specify a list of links to use for building
|
112
|
-
the `Link` header. You can set the links by manipulating the `links` hash.
|
113
|
-
|
114
|
-
For instance, here's how you could link to a post's comments and author:
|
115
|
-
|
116
|
-
```ruby
|
117
|
-
module API
|
118
|
-
module V1
|
119
|
-
module Post
|
120
|
-
module Operation
|
121
|
-
class Show < Pragma::Operation::Base
|
122
|
-
def call
|
123
|
-
post = ::Post.find(params[:id])
|
124
|
-
|
125
|
-
links['comments'] = "/posts/#{post.id}/comments"
|
126
|
-
links['author'] = "/users/#{post.author.id}"
|
127
|
-
|
128
|
-
respond_with resource: post
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
```
|
136
|
-
|
137
|
-
You can also set the links when calling `#respond_with`:
|
138
|
-
|
139
|
-
```ruby
|
140
|
-
module API
|
141
|
-
module V1
|
142
|
-
module Post
|
143
|
-
module Operation
|
144
|
-
class Show < Pragma::Operation::Base
|
145
|
-
def call
|
146
|
-
post = ::Post.find(params[:id])
|
147
|
-
|
148
|
-
respond_with resource: post, links: {
|
149
|
-
comments: "/posts/#{post.id}/comments",
|
150
|
-
author: "/users/#{post.author.id}"
|
151
|
-
}
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
```
|
159
|
-
|
160
|
-
This will build the `Link` header accordingly:
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
result = API::V1::Post::Operation::Show.call(params: { id: 1 })
|
164
|
-
|
165
|
-
result.status # => :ok
|
166
|
-
result.headers
|
167
|
-
# => {
|
168
|
-
# 'Link' => '</posts/1/comments>; rel="comments",
|
169
|
-
# </users/49>; rel="author"'
|
170
|
-
# }
|
171
|
-
```
|
172
|
-
|
173
|
-
**Note: Do not set the `Link` header manually, as it will be replaced when building links from the
|
174
|
-
`links` hash.**
|
175
|
-
|
176
|
-
## Handling errors
|
177
|
-
|
178
|
-
You can use the `#success?` and `#failure?` method to check whether an operation was successful. An
|
179
|
-
operation is considered successful when it returns a 2xx or 3xx status code:
|
180
|
-
|
181
|
-
```ruby
|
182
|
-
module API
|
183
|
-
module V1
|
184
|
-
module Ping
|
185
|
-
module Operation
|
186
|
-
class Create < Pragma::Operation::Base
|
187
|
-
def call
|
188
|
-
if params[:pong].blank?
|
189
|
-
return respond_with(
|
190
|
-
status: :unprocessable_entity,
|
191
|
-
resource: {
|
192
|
-
error_type: :missing_pong,
|
193
|
-
error_message: "You must provide a 'pong' parameter."
|
194
|
-
}
|
195
|
-
)
|
196
|
-
end
|
197
|
-
|
198
|
-
respond_with status: :ok, resource: { pong: params[:pong] }
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
```
|
206
|
-
|
207
|
-
Once more, here's an example usage of the above operation:
|
208
|
-
|
209
|
-
```ruby
|
210
|
-
result1 = API::V1::Ping::Operation::Create.call(params: { pong: '' })
|
211
|
-
result1.success? # => false
|
212
|
-
|
213
|
-
result2 = API::V1::Ping::Operation::Create.call(params: { pong: 'HELLO' })
|
214
|
-
result2.success? # => true
|
215
|
-
```
|
216
|
-
|
217
|
-
## Halting the execution
|
218
|
-
|
219
|
-
Both `#respond_with` and `#head` provide bang counterparts that halt the execution of the operation.
|
220
|
-
They are useful, for instance, in before callbacks.
|
221
|
-
|
222
|
-
The above operation can be rewritten like this:
|
223
|
-
|
224
|
-
```ruby
|
225
|
-
module API
|
226
|
-
module V1
|
227
|
-
module Ping
|
228
|
-
module Operation
|
229
|
-
class Create < Pragma::Operation::Base
|
230
|
-
before :validate_params
|
231
|
-
|
232
|
-
def call
|
233
|
-
respond_with status: :ok, resource: { pong: params[:pong] }
|
234
|
-
end
|
235
|
-
|
236
|
-
private
|
237
|
-
|
238
|
-
def validate_params
|
239
|
-
if params[:pong].blank?
|
240
|
-
respond_with!(
|
241
|
-
status: :unprocessable_entity,
|
242
|
-
resource: {
|
243
|
-
error_type: :missing_pong,
|
244
|
-
error_message: "You must provide a 'pong' parameter."
|
245
|
-
}
|
246
|
-
)
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
```
|
255
|
-
|
256
|
-
The result is identical:
|
257
|
-
|
258
|
-
```ruby
|
259
|
-
result1 = API::V1::Ping::Operation::Create.call(params: { pong: '' })
|
260
|
-
result1.success? # => false
|
261
|
-
|
262
|
-
result2 = API::V1::Ping::Operation::Create.call(params: { pong: 'HELLO' })
|
263
|
-
result2.success? # => true
|
264
|
-
```
|