sober_swag 0.1.0 → 0.2.0

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