sober_swag 0.1.0 → 0.2.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/config/rubocop_linter_action.yml +5 -0
  3. data/.github/workflows/lint.yml +15 -0
  4. data/.github/workflows/ruby.yml +23 -1
  5. data/.gitignore +3 -0
  6. data/.rubocop.yml +73 -1
  7. data/.ruby-version +1 -1
  8. data/Gemfile.lock +29 -5
  9. data/README.md +109 -0
  10. data/bin/console +15 -14
  11. data/docs/serializers.md +203 -0
  12. data/example/.rspec +1 -0
  13. data/example/.ruby-version +1 -1
  14. data/example/Gemfile +10 -6
  15. data/example/Gemfile.lock +96 -76
  16. data/example/app/controllers/people_controller.rb +37 -21
  17. data/example/app/controllers/posts_controller.rb +102 -0
  18. data/example/app/models/application_record.rb +3 -0
  19. data/example/app/models/person.rb +6 -0
  20. data/example/app/models/post.rb +9 -0
  21. data/example/app/output_objects/person_errors_output_object.rb +5 -0
  22. data/example/app/output_objects/person_output_object.rb +15 -0
  23. data/example/app/output_objects/post_output_object.rb +10 -0
  24. data/example/bin/bundle +24 -20
  25. data/example/bin/rails +1 -1
  26. data/example/bin/rake +1 -1
  27. data/example/config/application.rb +11 -7
  28. data/example/config/environments/development.rb +0 -1
  29. data/example/config/environments/production.rb +3 -3
  30. data/example/config/puma.rb +5 -5
  31. data/example/config/routes.rb +3 -0
  32. data/example/config/spring.rb +4 -4
  33. data/example/db/migrate/20200311152021_create_people.rb +0 -1
  34. data/example/db/migrate/20200603172347_create_posts.rb +11 -0
  35. data/example/db/schema.rb +16 -7
  36. data/example/spec/rails_helper.rb +64 -0
  37. data/example/spec/requests/people/create_spec.rb +52 -0
  38. data/example/spec/requests/people/get_spec.rb +35 -0
  39. data/example/spec/requests/people/index_spec.rb +69 -0
  40. data/example/spec/spec_helper.rb +94 -0
  41. data/lib/sober_swag.rb +6 -3
  42. data/lib/sober_swag/compiler/error.rb +2 -0
  43. data/lib/sober_swag/compiler/path.rb +2 -5
  44. data/lib/sober_swag/compiler/paths.rb +0 -1
  45. data/lib/sober_swag/compiler/type.rb +28 -15
  46. data/lib/sober_swag/controller.rb +16 -11
  47. data/lib/sober_swag/controller/route.rb +18 -21
  48. data/lib/sober_swag/controller/undefined_body_error.rb +3 -0
  49. data/lib/sober_swag/controller/undefined_path_error.rb +3 -0
  50. data/lib/sober_swag/controller/undefined_query_error.rb +3 -0
  51. data/lib/sober_swag/input_object.rb +28 -0
  52. data/lib/sober_swag/nodes/array.rb +1 -1
  53. data/lib/sober_swag/nodes/base.rb +2 -4
  54. data/lib/sober_swag/nodes/binary.rb +2 -1
  55. data/lib/sober_swag/nodes/enum.rb +4 -2
  56. data/lib/sober_swag/nodes/list.rb +0 -1
  57. data/lib/sober_swag/nodes/primitive.rb +6 -5
  58. data/lib/sober_swag/output_object.rb +102 -0
  59. data/lib/sober_swag/output_object/definition.rb +30 -0
  60. data/lib/sober_swag/{blueprint → output_object}/field.rb +14 -4
  61. data/lib/sober_swag/{blueprint → output_object}/field_syntax.rb +1 -1
  62. data/lib/sober_swag/{blueprint → output_object}/view.rb +15 -6
  63. data/lib/sober_swag/parser.rb +5 -3
  64. data/lib/sober_swag/serializer.rb +5 -2
  65. data/lib/sober_swag/serializer/array.rb +12 -0
  66. data/lib/sober_swag/serializer/base.rb +50 -1
  67. data/lib/sober_swag/serializer/conditional.rb +15 -2
  68. data/lib/sober_swag/serializer/field_list.rb +29 -6
  69. data/lib/sober_swag/serializer/mapped.rb +12 -2
  70. data/lib/sober_swag/serializer/meta.rb +35 -0
  71. data/lib/sober_swag/serializer/optional.rb +17 -2
  72. data/lib/sober_swag/serializer/primitive.rb +4 -1
  73. data/lib/sober_swag/server.rb +83 -0
  74. data/lib/sober_swag/types.rb +3 -0
  75. data/lib/sober_swag/version.rb +1 -1
  76. data/sober_swag.gemspec +6 -4
  77. metadata +77 -44
  78. data/example/person.json +0 -4
  79. data/example/test/controllers/.keep +0 -0
  80. data/example/test/fixtures/.keep +0 -0
  81. data/example/test/fixtures/files/.keep +0 -0
  82. data/example/test/fixtures/people.yml +0 -11
  83. data/example/test/integration/.keep +0 -0
  84. data/example/test/models/.keep +0 -0
  85. data/example/test/models/person_test.rb +0 -7
  86. data/example/test/test_helper.rb +0 -13
  87. data/lib/sober_swag/blueprint.rb +0 -113
  88. data/lib/sober_swag/path.rb +0 -8
  89. data/lib/sober_swag/path/integer.rb +0 -21
  90. data/lib/sober_swag/path/lit.rb +0 -41
  91. data/lib/sober_swag/path/literal.rb +0 -29
  92. data/lib/sober_swag/path/param.rb +0 -33
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -1 +1 @@
1
- 2.7.0
1
+ 2.7.1
@@ -1,14 +1,16 @@
1
1
  source 'https://rubygems.org'
2
2
  git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
3
 
4
- ruby '2.7.0'
4
+ ruby '2.7.1'
5
5
 
6
6
  # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7
- gem 'rails', '~> 6.0.2', '>= 6.0.2.1'
7
+ gem 'rails', '~> 6.0.2', '>= 6.0.2.2'
8
+
9
+ gem 'actionpack', '>= 6.0.3.2'
8
10
  # Use sqlite3 as the database for Active Record
9
11
  gem 'sqlite3', '~> 1.4'
10
12
  # Use Puma as the app server
11
- gem 'puma', '~> 4.1'
13
+ gem 'puma', '~> 4.3'
12
14
  # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
13
15
  # gem 'jbuilder', '~> 2.7'
14
16
  # Use Active Model has_secure_password
@@ -20,14 +22,16 @@ gem 'bootsnap', '>= 1.4.2', require: false
20
22
  # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
21
23
  # gem 'rack-cors'
22
24
 
23
- gem 'sober_swag', path: '..'
25
+ gem 'sober_swag', path: '..'
24
26
 
25
27
  group :development, :test do
26
28
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
27
- gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
29
+ gem 'byebug', platforms: %i[mri mingw x64_mingw]
28
30
 
29
31
  gem 'dry-types-rails'
30
32
 
33
+ gem 'rspec-rails'
34
+
31
35
  gem 'pry'
32
36
  end
33
37
 
@@ -39,4 +43,4 @@ group :development do
39
43
  end
40
44
 
41
45
  # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
42
- gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
46
+ gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
@@ -9,69 +9,70 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actioncable (6.0.2.1)
13
- actionpack (= 6.0.2.1)
12
+ actioncable (6.0.3.2)
13
+ actionpack (= 6.0.3.2)
14
14
  nio4r (~> 2.0)
15
15
  websocket-driver (>= 0.6.1)
16
- actionmailbox (6.0.2.1)
17
- actionpack (= 6.0.2.1)
18
- activejob (= 6.0.2.1)
19
- activerecord (= 6.0.2.1)
20
- activestorage (= 6.0.2.1)
21
- activesupport (= 6.0.2.1)
16
+ actionmailbox (6.0.3.2)
17
+ actionpack (= 6.0.3.2)
18
+ activejob (= 6.0.3.2)
19
+ activerecord (= 6.0.3.2)
20
+ activestorage (= 6.0.3.2)
21
+ activesupport (= 6.0.3.2)
22
22
  mail (>= 2.7.1)
23
- actionmailer (6.0.2.1)
24
- actionpack (= 6.0.2.1)
25
- actionview (= 6.0.2.1)
26
- activejob (= 6.0.2.1)
23
+ actionmailer (6.0.3.2)
24
+ actionpack (= 6.0.3.2)
25
+ actionview (= 6.0.3.2)
26
+ activejob (= 6.0.3.2)
27
27
  mail (~> 2.5, >= 2.5.4)
28
28
  rails-dom-testing (~> 2.0)
29
- actionpack (6.0.2.1)
30
- actionview (= 6.0.2.1)
31
- activesupport (= 6.0.2.1)
29
+ actionpack (6.0.3.2)
30
+ actionview (= 6.0.3.2)
31
+ activesupport (= 6.0.3.2)
32
32
  rack (~> 2.0, >= 2.0.8)
33
33
  rack-test (>= 0.6.3)
34
34
  rails-dom-testing (~> 2.0)
35
35
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
36
- actiontext (6.0.2.1)
37
- actionpack (= 6.0.2.1)
38
- activerecord (= 6.0.2.1)
39
- activestorage (= 6.0.2.1)
40
- activesupport (= 6.0.2.1)
36
+ actiontext (6.0.3.2)
37
+ actionpack (= 6.0.3.2)
38
+ activerecord (= 6.0.3.2)
39
+ activestorage (= 6.0.3.2)
40
+ activesupport (= 6.0.3.2)
41
41
  nokogiri (>= 1.8.5)
42
- actionview (6.0.2.1)
43
- activesupport (= 6.0.2.1)
42
+ actionview (6.0.3.2)
43
+ activesupport (= 6.0.3.2)
44
44
  builder (~> 3.1)
45
45
  erubi (~> 1.4)
46
46
  rails-dom-testing (~> 2.0)
47
47
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
48
- activejob (6.0.2.1)
49
- activesupport (= 6.0.2.1)
48
+ activejob (6.0.3.2)
49
+ activesupport (= 6.0.3.2)
50
50
  globalid (>= 0.3.6)
51
- activemodel (6.0.2.1)
52
- activesupport (= 6.0.2.1)
53
- activerecord (6.0.2.1)
54
- activemodel (= 6.0.2.1)
55
- activesupport (= 6.0.2.1)
56
- activestorage (6.0.2.1)
57
- actionpack (= 6.0.2.1)
58
- activejob (= 6.0.2.1)
59
- activerecord (= 6.0.2.1)
51
+ activemodel (6.0.3.2)
52
+ activesupport (= 6.0.3.2)
53
+ activerecord (6.0.3.2)
54
+ activemodel (= 6.0.3.2)
55
+ activesupport (= 6.0.3.2)
56
+ activestorage (6.0.3.2)
57
+ actionpack (= 6.0.3.2)
58
+ activejob (= 6.0.3.2)
59
+ activerecord (= 6.0.3.2)
60
60
  marcel (~> 0.3.1)
61
- activesupport (6.0.2.1)
61
+ activesupport (6.0.3.2)
62
62
  concurrent-ruby (~> 1.0, >= 1.0.2)
63
63
  i18n (>= 0.7, < 2)
64
64
  minitest (~> 5.1)
65
65
  tzinfo (~> 1.1)
66
- zeitwerk (~> 2.2)
66
+ zeitwerk (~> 2.2, >= 2.2.2)
67
67
  bootsnap (1.4.6)
68
68
  msgpack (~> 1.0)
69
69
  builder (3.2.4)
70
- byebug (11.1.1)
71
- coderay (1.1.2)
70
+ byebug (11.1.3)
71
+ coderay (1.1.3)
72
72
  concurrent-ruby (1.1.6)
73
73
  crass (1.0.6)
74
- dry-configurable (0.11.3)
74
+ diff-lcs (1.4.4)
75
+ dry-configurable (0.11.6)
75
76
  concurrent-ruby (~> 1.0)
76
77
  dry-core (~> 0.4, >= 0.4.7)
77
78
  dry-equalizer (~> 0.2)
@@ -102,76 +103,93 @@ GEM
102
103
  dry-types (>= 0.8.1)
103
104
  rails (>= 3)
104
105
  erubi (1.9.0)
105
- ffi (1.12.2)
106
+ ffi (1.13.1)
106
107
  globalid (0.4.2)
107
108
  activesupport (>= 4.2.0)
108
- i18n (1.8.2)
109
+ i18n (1.8.3)
109
110
  concurrent-ruby (~> 1.0)
110
111
  ice_nine (0.11.2)
111
112
  listen (3.1.5)
112
113
  rb-fsevent (~> 0.9, >= 0.9.4)
113
114
  rb-inotify (~> 0.9, >= 0.9.7)
114
115
  ruby_dep (~> 1.2)
115
- loofah (2.4.0)
116
+ loofah (2.6.0)
116
117
  crass (~> 1.0.2)
117
118
  nokogiri (>= 1.5.9)
118
119
  mail (2.7.1)
119
120
  mini_mime (>= 0.1.1)
120
121
  marcel (0.3.3)
121
122
  mimemagic (~> 0.3.2)
122
- method_source (0.9.2)
123
- mimemagic (0.3.4)
123
+ method_source (1.0.0)
124
+ mimemagic (0.3.5)
124
125
  mini_mime (1.0.2)
125
126
  mini_portile2 (2.4.0)
126
- minitest (5.14.0)
127
+ minitest (5.14.1)
127
128
  msgpack (1.3.3)
128
129
  nio4r (2.5.2)
129
- nokogiri (1.10.9)
130
+ nokogiri (1.10.10)
130
131
  mini_portile2 (~> 2.4.0)
131
- pry (0.12.2)
132
- coderay (~> 1.1.0)
133
- method_source (~> 0.9.0)
134
- puma (4.3.3)
132
+ pry (0.13.1)
133
+ coderay (~> 1.1)
134
+ method_source (~> 1.0)
135
+ puma (4.3.5)
135
136
  nio4r (~> 2.0)
136
- rack (2.2.2)
137
+ rack (2.2.3)
137
138
  rack-test (1.1.0)
138
139
  rack (>= 1.0, < 3)
139
- rails (6.0.2.1)
140
- actioncable (= 6.0.2.1)
141
- actionmailbox (= 6.0.2.1)
142
- actionmailer (= 6.0.2.1)
143
- actionpack (= 6.0.2.1)
144
- actiontext (= 6.0.2.1)
145
- actionview (= 6.0.2.1)
146
- activejob (= 6.0.2.1)
147
- activemodel (= 6.0.2.1)
148
- activerecord (= 6.0.2.1)
149
- activestorage (= 6.0.2.1)
150
- activesupport (= 6.0.2.1)
140
+ rails (6.0.3.2)
141
+ actioncable (= 6.0.3.2)
142
+ actionmailbox (= 6.0.3.2)
143
+ actionmailer (= 6.0.3.2)
144
+ actionpack (= 6.0.3.2)
145
+ actiontext (= 6.0.3.2)
146
+ actionview (= 6.0.3.2)
147
+ activejob (= 6.0.3.2)
148
+ activemodel (= 6.0.3.2)
149
+ activerecord (= 6.0.3.2)
150
+ activestorage (= 6.0.3.2)
151
+ activesupport (= 6.0.3.2)
151
152
  bundler (>= 1.3.0)
152
- railties (= 6.0.2.1)
153
+ railties (= 6.0.3.2)
153
154
  sprockets-rails (>= 2.0.0)
154
155
  rails-dom-testing (2.0.3)
155
156
  activesupport (>= 4.2.0)
156
157
  nokogiri (>= 1.6)
157
158
  rails-html-sanitizer (1.3.0)
158
159
  loofah (~> 2.3)
159
- railties (6.0.2.1)
160
- actionpack (= 6.0.2.1)
161
- activesupport (= 6.0.2.1)
160
+ railties (6.0.3.2)
161
+ actionpack (= 6.0.3.2)
162
+ activesupport (= 6.0.3.2)
162
163
  method_source
163
164
  rake (>= 0.8.7)
164
165
  thor (>= 0.20.3, < 2.0)
165
166
  rake (13.0.1)
166
- rb-fsevent (0.10.3)
167
+ rb-fsevent (0.10.4)
167
168
  rb-inotify (0.10.1)
168
169
  ffi (~> 1.0)
170
+ rspec-core (3.9.2)
171
+ rspec-support (~> 3.9.3)
172
+ rspec-expectations (3.9.2)
173
+ diff-lcs (>= 1.2.0, < 2.0)
174
+ rspec-support (~> 3.9.0)
175
+ rspec-mocks (3.9.1)
176
+ diff-lcs (>= 1.2.0, < 2.0)
177
+ rspec-support (~> 3.9.0)
178
+ rspec-rails (4.0.1)
179
+ actionpack (>= 4.2)
180
+ activesupport (>= 4.2)
181
+ railties (>= 4.2)
182
+ rspec-core (~> 3.9)
183
+ rspec-expectations (~> 3.9)
184
+ rspec-mocks (~> 3.9)
185
+ rspec-support (~> 3.9)
186
+ rspec-support (3.9.3)
169
187
  ruby_dep (1.5.0)
170
188
  spring (2.1.0)
171
189
  spring-watcher-listen (2.0.1)
172
190
  listen (>= 2.7, < 4.0)
173
191
  spring (>= 1.2, < 3.0)
174
- sprockets (4.0.0)
192
+ sprockets (4.0.2)
175
193
  concurrent-ruby (~> 1.0)
176
194
  rack (> 1, < 3)
177
195
  sprockets-rails (3.2.1)
@@ -181,24 +199,26 @@ GEM
181
199
  sqlite3 (1.4.2)
182
200
  thor (1.0.1)
183
201
  thread_safe (0.3.6)
184
- tzinfo (1.2.6)
202
+ tzinfo (1.2.7)
185
203
  thread_safe (~> 0.1)
186
- websocket-driver (0.7.1)
204
+ websocket-driver (0.7.3)
187
205
  websocket-extensions (>= 0.1.0)
188
- websocket-extensions (0.1.4)
189
- zeitwerk (2.3.0)
206
+ websocket-extensions (0.1.5)
207
+ zeitwerk (2.4.0)
190
208
 
191
209
  PLATFORMS
192
210
  ruby
193
211
 
194
212
  DEPENDENCIES
213
+ actionpack (>= 6.0.3.2)
195
214
  bootsnap (>= 1.4.2)
196
215
  byebug
197
216
  dry-types-rails
198
217
  listen (>= 3.0.5, < 3.2)
199
218
  pry
200
- puma (~> 4.1)
201
- rails (~> 6.0.2, >= 6.0.2.1)
219
+ puma (~> 4.3)
220
+ rails (~> 6.0.2, >= 6.0.2.2)
221
+ rspec-rails
202
222
  sober_swag!
203
223
  spring
204
224
  spring-watcher-listen (~> 2.0.0)
@@ -206,7 +226,7 @@ DEPENDENCIES
206
226
  tzinfo-data
207
227
 
208
228
  RUBY VERSION
209
- ruby 2.7.0p0
229
+ ruby 2.7.1p83
210
230
 
211
231
  BUNDLED WITH
212
- 2.1.2
232
+ 2.1.4
@@ -1,45 +1,61 @@
1
+ ##
2
+ # Demonstration controller that involves people.
1
3
  class PeopleController < ApplicationController
2
-
3
4
  include SoberSwag::Controller
4
5
 
5
6
  before_action :load_person, only: %i[show update]
6
7
 
8
+ PersonBodyParams = SoberSwag.input_object do
9
+ identifier 'PersonBodyParams'
7
10
 
8
- PersonBodyParams = SoberSwag.struct do
9
11
  attribute :first_name, SoberSwag::Types::String
10
12
  attribute :last_name, SoberSwag::Types::String
11
13
  attribute? :date_of_birth, SoberSwag::Types::Params::DateTime.optional
12
14
  end
13
15
 
14
- PersonParams = SoberSwag.struct do
16
+ PersonBodyPatchParams = SoberSwag.input_object(PersonBodyParams) do
17
+ identifier 'PersonBodyPatchParams'
18
+
19
+ attribute? :first_name, SoberSwag::Types::String
20
+ attribute? :last_name, SoberSwag::Types::String
21
+ attribute? :date_of_birth, SoberSwag::Types::Params::DateTime.optional
22
+ end
23
+
24
+ PersonParams = SoberSwag.input_object do
25
+ identifier 'PersonParams'
15
26
  attribute :person, PersonBodyParams
16
27
  end
17
28
 
18
- PersonSerializer = SoberSwag::Blueprint.define do
19
- field :id, primitive(:Integer)
20
- field :first_name, primitive(:String)
21
- field :last_name, primitive(:String)
29
+ PersonPatchParams = SoberSwag.input_object do
30
+ identifier 'PersonPatchParams'
31
+ attribute :person, PersonBodyPatchParams
22
32
  end
23
33
 
24
34
  define :post, :create, '/people/' do
25
35
  request_body(PersonParams)
26
- response(:ok, 'the person created', PersonSerializer)
36
+ response(:ok, 'the person created', PersonOutputObject)
37
+ response(:unprocessable_entity, 'the validation errors', PersonErrorsOutputObject)
27
38
  end
28
39
  def create
29
- p = Person.create!(parsed_body.to_h)
30
- respond!(:ok, p)
40
+ p = Person.new(parsed_body.person.to_h)
41
+ if p.save
42
+ respond!(:ok, p)
43
+ else
44
+ respond!(:unprocessable_entity, p.errors)
45
+ end
31
46
  end
32
47
 
33
48
  define :patch, :update, '/people/{id}' do
34
- request_body(PersonParams)
49
+ request_body(PersonPatchParams)
35
50
  path_params { attribute :id, Types::Params::Integer }
36
- response(:ok, 'the person updated', PersonSerializer)
51
+ response(:ok, 'the person updated', PersonOutputObject)
52
+ response(:unprocessable_entity, 'the validation errors', PersonErrorsOutputObject)
37
53
  end
38
54
  def update
39
- if @person.update(parsed_body.to_h)
55
+ if @person.update(parsed_body.person.to_h)
40
56
  respond!(:ok, @person)
41
57
  else
42
- render json: @person.errors, status: :unprocessable_entity
58
+ respond!(:unprocessable_entity, @person.errors)
43
59
  end
44
60
  end
45
61
 
@@ -47,22 +63,22 @@ class PeopleController < ApplicationController
47
63
  query_params do
48
64
  attribute? :first_name, Types::String
49
65
  attribute? :last_name, Types::String
66
+ attribute? :view, Types::String.enum('base', 'detail')
50
67
  end
51
- response(:ok, 'all the people', PersonSerializer.new.array)
68
+ response(:ok, 'all the people', PersonOutputObject.array)
52
69
  end
53
-
54
70
  def index
55
71
  @people = Person.all
56
- @people = @people.where('first_name ILIKE ?', "%#{parsed_query.first_name}%") if parsed_query.first_name
57
- @people = @people.where('last_name ILIKE ?', "%#{parsed_query.last_name}%") if parsed_query.last_name
58
- respond!(:ok, @people)
59
- end
72
+ @people = @people.where('UPPER(first_name) LIKE UPPER(?)', "%#{parsed_query.first_name}%") if parsed_query.first_name
73
+ @people = @people.where('UPPER(last_name) LIKE UPPER(?)', "%#{parsed_query.last_name}%") if parsed_query.last_name
74
+ respond!(:ok, @people.includes(:posts), serializer_opts: { view: parsed_query.view })
75
+ end
60
76
 
61
77
  define :get, :show, '/people/{id}' do
62
78
  path_params do
63
79
  attribute :id, Types::Params::Integer
64
80
  end
65
- response(:ok, 'the person requested', PersonSerializer.new)
81
+ response(:ok, 'the person requested', PersonOutputObject)
66
82
  end
67
83
  def show
68
84
  respond!(:ok, @person)
@@ -0,0 +1,102 @@
1
+ ##
2
+ # Example controller for posts.
3
+ class PostsController < ApplicationController
4
+ before_action :set_post, only: %i[show update destroy]
5
+
6
+ include SoberSwag::Controller
7
+
8
+ PostCreateParamsBody = SoberSwag.input_object do
9
+ identifier 'PostCreateParamsBody'
10
+ attribute :person_id, SoberSwag::Types::Params::Integer.meta(description: 'Unique ID obtained from a person')
11
+ attribute :title, SoberSwag::Types::String.meta(description: 'Short title of a post')
12
+ attribute :body, SoberSwag::Types::String.meta(description: 'Post body in markdown format')
13
+ end
14
+
15
+ PostCreate = SoberSwag.input_object do
16
+ identifier 'PostCreate'
17
+ attribute :post, PostCreateParamsBody
18
+ end
19
+
20
+ PostUpdateParamsBody = SoberSwag.input_object do
21
+ identifier 'PostUpdateParamsBody'
22
+ attribute? :person_id, SoberSwag::Types::Params::Integer
23
+ attribute? :title, SoberSwag::Types::String
24
+ attribute? :body, SoberSwag::Types::String
25
+ end
26
+
27
+ PostUpdate = SoberSwag.input_object do
28
+ identifier 'PostUpdate'
29
+ attribute :post, PostUpdateParamsBody
30
+ end
31
+
32
+ ViewTypes = SoberSwag::Types::String.enum('base', 'detail')
33
+
34
+ ShowPath = SoberSwag.input_object do
35
+ identifier 'ShowPersonPathParams'
36
+ attribute :id, Types::Params::Integer
37
+ end
38
+
39
+ define :get, :index, '/posts/' do
40
+ query_params do
41
+ attribute? :view, ViewTypes
42
+ end
43
+ response(:ok, 'all the posts', PostOutputObject.array)
44
+ end
45
+ def index
46
+ @posts = Post.all
47
+
48
+ respond!(:ok, @posts.includes(:person), serializer_opts: { view: parsed_query.view })
49
+ end
50
+
51
+ define :get, :show, '/posts/{id}' do
52
+ path_params(ShowPath)
53
+ query_params { attribute? :view, ViewTypes }
54
+ response(:ok, 'the requested post', PostOutputObject)
55
+ end
56
+ def show
57
+ respond!(:ok, @post, serializer_opts: { view: parsed_query.view })
58
+ end
59
+
60
+ define :post, :create, '/posts/' do
61
+ request_body(PostCreate)
62
+ response(:created, 'the created post', PostOutputObject)
63
+ end
64
+ def create
65
+ @post = Post.new(parsed_body.post.to_h)
66
+
67
+ if @post.save
68
+ respond! :created, @post, rails_opts: { location: @post }
69
+ else
70
+ render json: @post.errors, status: :unprocessable_entity
71
+ end
72
+ end
73
+
74
+ define :patch, :update, '/posts/{id}' do
75
+ path_params(ShowPath)
76
+ request_body(PostUpdate)
77
+ response(:ok, 'the post updated', PostOutputObject.view(:base))
78
+ end
79
+ def update
80
+ if @post.update(parsed_body.post.to_h)
81
+ respond!(:ok, @post)
82
+ else
83
+ render json: @post.errors, status: :unprocessable_entity
84
+ end
85
+ end
86
+
87
+ define :delete, :destroy, '/posts/{id}' do
88
+ path_params(ShowPath)
89
+ response(:ok, 'the post deleted', PostOutputObject.view(:base))
90
+ end
91
+ def destroy
92
+ @post.destroy
93
+ respond!(:ok, @post)
94
+ end
95
+
96
+ private
97
+
98
+ # Use callbacks to share common setup or constraints between actions.
99
+ def set_post
100
+ @post = Post.find(parsed_path.id)
101
+ end
102
+ end