apicasso 0.4.11 → 0.5.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -3
  3. data/Rakefile +0 -0
  4. data/app/controllers/apicasso/apidocs_controller.rb +332 -326
  5. data/app/controllers/apicasso/application_controller.rb +46 -1
  6. data/app/controllers/apicasso/crud_controller.rb +4 -20
  7. data/app/controllers/concerns/orderable.rb +1 -1
  8. data/app/controllers/concerns/sql_security.rb +67 -0
  9. data/app/models/apicasso/ability.rb +3 -0
  10. data/app/models/apicasso/application_record.rb +0 -0
  11. data/app/models/apicasso/key.rb +0 -0
  12. data/app/models/apicasso/request.rb +0 -0
  13. data/config/routes.rb +7 -0
  14. data/lib/apicasso/active_record_extension.rb +5 -0
  15. data/lib/apicasso/engine.rb +0 -0
  16. data/lib/apicasso/version.rb +1 -1
  17. data/lib/apicasso.rb +0 -0
  18. data/lib/generators/apicasso/install/install_generator.rb +6 -0
  19. data/lib/generators/apicasso/install/templates/create_apicasso_tables.rb +8 -0
  20. data/spec/apicasso_spec.rb +0 -0
  21. data/spec/dummy/Gemfile +0 -0
  22. data/spec/dummy/Gemfile.lock +0 -0
  23. data/spec/dummy/Rakefile +0 -0
  24. data/spec/dummy/app/controllers/application_controller.rb +0 -0
  25. data/spec/dummy/app/models/application_record.rb +0 -0
  26. data/spec/dummy/app/models/used_model.rb +0 -0
  27. data/spec/dummy/bin/bundle +0 -0
  28. data/spec/dummy/bin/rails +0 -0
  29. data/spec/dummy/bin/rake +0 -0
  30. data/spec/dummy/bin/setup +0 -0
  31. data/spec/dummy/bin/spring +0 -0
  32. data/spec/dummy/bin/update +0 -0
  33. data/spec/dummy/config/application.rb +0 -0
  34. data/spec/dummy/config/boot.rb +0 -0
  35. data/spec/dummy/config/cable.yml +0 -0
  36. data/spec/dummy/config/credentials.yml.enc +0 -0
  37. data/spec/dummy/config/database.yml +0 -0
  38. data/spec/dummy/config/environment.rb +0 -0
  39. data/spec/dummy/config/environments/development.rb +0 -0
  40. data/spec/dummy/config/environments/production.rb +0 -0
  41. data/spec/dummy/config/environments/test.rb +0 -0
  42. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -0
  43. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -0
  44. data/spec/dummy/config/initializers/cors.rb +0 -0
  45. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -0
  46. data/spec/dummy/config/initializers/inflections.rb +0 -0
  47. data/spec/dummy/config/initializers/mime_types.rb +0 -0
  48. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -0
  49. data/spec/dummy/config/locales/en.yml +0 -0
  50. data/spec/dummy/config/puma.rb +0 -0
  51. data/spec/dummy/config/routes.rb +0 -0
  52. data/spec/dummy/config/spring.rb +0 -0
  53. data/spec/dummy/config/storage.yml +0 -0
  54. data/spec/dummy/config.ru +0 -0
  55. data/spec/dummy/db/migrate/20180918134607_create_apicasso_tables.rb +0 -0
  56. data/spec/dummy/db/migrate/20180918141254_create_used_models.rb +0 -0
  57. data/spec/dummy/db/migrate/20180919130152_create_active_storage_tables.active_storage.rb +0 -0
  58. data/spec/dummy/db/migrate/20180920133933_change_used_model_to_validates.rb +0 -0
  59. data/spec/dummy/db/schema.rb +0 -0
  60. data/spec/dummy/db/seeds.rb +0 -0
  61. data/spec/dummy/package.json +0 -0
  62. data/spec/factories/used_model.rb +0 -0
  63. data/spec/models/used_model_spec.rb +0 -0
  64. data/spec/rails_helper.rb +0 -0
  65. data/spec/requests/bad_requests_spec.rb +51 -0
  66. data/spec/requests/requests_spec.rb +98 -23
  67. data/spec/spec_helper.rb +1 -1
  68. data/spec/support/database_cleaner.rb +8 -0
  69. data/spec/support/factory_bot.rb +0 -0
  70. data/spec/token/token_spec.rb +322 -0
  71. metadata +32 -27
  72. data/spec/dummy/app/serializers/used_model_serializer.rb +0 -3
@@ -8,6 +8,9 @@ module Apicasso
8
8
 
9
9
  include Swagger::Blocks
10
10
 
11
+ # Default application settings for documentation generation.
12
+ # Define here the title of the application, logo, description, terms
13
+ # of service, contact of the developer and the license of the application.
11
14
  swagger_root do
12
15
  MODELS_EXCLUDED = [
13
16
  'ApplicationRecord',
@@ -22,6 +25,7 @@ module Apicasso
22
25
  key :swagger, '2.0'
23
26
  info do
24
27
  key :title, ENV.fetch('APP_NAME', I18n.t('application.name'))
28
+ # The x-logo key is responsible for the logo in the documentation
25
29
  key 'x-logo', { url: I18n.t('app.logo.url', default: 'https://raw.githubusercontent.com/ErvalhouS/APIcasso/master/APIcasso.png'), altText: I18n.t('app.logo.alttext', default: 'Application Logo')}
26
30
  key :description, ENV.fetch('APP_DESCRIPTION', I18n.t('application.description'))
27
31
  key :termsOfService, I18n.t('application.terms_of_service')
@@ -32,6 +36,7 @@ module Apicasso
32
36
  key :name, I18n.t('application.license')
33
37
  end
34
38
  end
39
+ # Auto generated default application setting for each model of application
35
40
  ActiveRecord::Base.descendants.each do |model|
36
41
  next if MODELS_EXCLUDED.include?(model.name) || model.abstract_class
37
42
 
@@ -54,8 +59,8 @@ module Apicasso
54
59
 
55
60
  # Eager load application to be able to list all models
56
61
  Rails.application.eager_load! unless Rails.configuration.cache_classes
57
- # A list of all classes that have swagger_* declarations, which gets injected
58
- # by this gem in all `ActiveRecord::Base` classes
62
+ # A list of all classes that have swagger_* declarations, which gets
63
+ # injected by this gem in all `ActiveRecord::Base` classes
59
64
  SWAGGERED_CLASSES = [
60
65
  *ActiveRecord::Base.descendants,
61
66
  self
@@ -75,6 +80,7 @@ module Apicasso
75
80
  end
76
81
  end
77
82
 
83
+ # Generate metadata to each class of application
78
84
  SWAGGERED_CLASSES.each do |klass|
79
85
  next if MODELS_EXCLUDED.include?(klass.name) || klass.abstract_class
80
86
 
@@ -118,377 +124,377 @@ module Apicasso
118
124
  end
119
125
  end
120
126
 
121
- ActiveRecord::Base.descendants.each do |model|
122
- next if MODELS_EXCLUDED.include?(model.name) || model.abstract_class
123
-
124
- swagger_path "/#{model.name.underscore}" do
125
- operation :get do
126
- key :summary, I18n.t("activerecord.models.#{model.name.underscore}.index.summary", default: model.name)
127
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.description", default: model.name)
128
- key :operationId, "find#{model.name.pluralize}"
129
- key :produces, ['application/json']
130
- key :tags, [model.name.underscore]
131
- parameter do
132
- key :name, :sort
133
- key :in, :query
134
- key :description, I18n.t('apicasso.sort.description',
135
- default: 'Parameters sorting splitted by `,` preffixed by `+` or `-` which translates into ascending or descending order')
127
+ # Builds JSON of definitions with operations from each model
128
+ next if MODELS_EXCLUDED.include?(model.name) || model.abstract_class
129
+ # Resource definitions of GET, OPTIONS, POST
130
+ swagger_path "/#{model.name.underscore}" do
131
+ operation :get do
132
+ key :summary, I18n.t("activerecord.models.#{model.name.underscore}.index.summary", default: model.name)
133
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.description", default: model.name)
134
+ key :operationId, "find#{model.name.pluralize}"
135
+ key :produces, ['application/json']
136
+ key :tags, [model.name.underscore]
137
+ parameter do
138
+ key :name, :sort
139
+ key :in, :query
140
+ key :description, I18n.t('apicasso.sort.description',
141
+ default: 'Parameters sorting splitted by `,` preffixed by `+` or `-` which translates into ascending or descending order')
142
+ key :required, false
143
+ key :type, :string
144
+ key :collectionFormat, :json
145
+ end
146
+ parameter do
147
+ key :name, :q
148
+ key :in, :query
149
+ key :description, I18n.t('apicasso.q.description',
150
+ default: 'Records filtering by attribute and search query as affix. Usage: `?q[{attribute}{search_affix}]={matcher}`. All available search affixes are listed on: https://github.com/activerecord-hackery/ransack#search-matchers')
151
+ key :required, false
152
+ key :type, :json
153
+ end
154
+ parameter do
155
+ key :name, :page
156
+ key :in, :query
157
+ key :description, I18n.t('apicasso.page.description',
158
+ default: 'Records pagination paging, which offsets collection based on `params[:per_page]`')
159
+ key :required, false
160
+ key :type, :integer
161
+ end
162
+ parameter do
163
+ key :name, :per_page
164
+ key :in, :query
165
+ key :description, I18n.t('apicasso.per_page.description',
166
+ default: 'Records pagination size, which sets how many records will be rendered per request')
167
+ key :required, false
168
+ key :type, :integer
169
+ end
170
+ response 200 do
171
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.response",
172
+ default: "#{model.name} response, which include records matching current query and pagination metadata")
173
+ schema do
174
+ key :name, :total
175
+ key :description, I18n.t('apicasso.total.description',
176
+ default: 'Total records contained in current collection, as if there was no pagination.')
177
+ key :required, true
178
+ key :type, :integer
179
+ end
180
+ schema do
181
+ key :name, :total_pages
182
+ key :description, I18n.t('apicasso.total_pages.description',
183
+ default: 'How many pages of data the current collection has.')
184
+ key :required, true
185
+ key :type, :integer
186
+ end
187
+ schema do
188
+ key :name, :last_page
189
+ key :description, I18n.t('apicasso.last_page.description',
190
+ default: 'An indication if current request is the last to paginate in the current collection')
191
+ key :required, true
192
+ key :type, :boolean
193
+ end
194
+ schema do
195
+ key :name, :previous_page
196
+ key :description, I18n.t('apicasso.previous_page.description',
197
+ default: "The link of the previous page for the current collection. It can be null if there isn't any")
136
198
  key :required, false
137
199
  key :type, :string
138
- key :collectionFormat, :json
139
200
  end
140
- parameter do
141
- key :name, :q
142
- key :in, :query
143
- key :description, I18n.t('apicasso.q.description',
144
- default: 'Records filtering by attribute and search query as affix. Usage: `?q[{attribute}{search_affix}]={matcher}`. All available search affixes are listed on: https://github.com/activerecord-hackery/ransack#search-matchers')
201
+ schema do
202
+ key :name, :next_page
203
+ key :description, I18n.t('apicasso.next_page.description',
204
+ default: "The link of the next page for the current collection. It can be null if there isn't any")
145
205
  key :required, false
146
- key :type, :json
206
+ key :type, :string
147
207
  end
148
- parameter do
149
- key :name, :page
150
- key :in, :query
151
- key :description, I18n.t('apicasso.page.description',
152
- default: 'Records pagination paging, which offsets collection based on `params[:per_page]`')
153
- key :required, false
154
- key :type, :integer
208
+ schema do
209
+ key :name, :out_of_bounds
210
+ key :description, I18n.t('apicasso.out_of_bounds.description',
211
+ default: 'An indication if current request is out of pagination bounds for the current collection')
212
+ key :required, true
213
+ key :type, :boolean
155
214
  end
156
- parameter do
157
- key :name, :per_page
158
- key :in, :query
159
- key :description, I18n.t('apicasso.per_page.description',
160
- default: 'Records pagination size, which sets how many records will be rendered per request')
161
- key :required, false
215
+ schema do
216
+ key :name, :offset
217
+ key :description, I18n.t('apicasso.offset.description',
218
+ default: 'How many records were offsetted from the collection to render the current page')
219
+ key :required, true
162
220
  key :type, :integer
163
221
  end
164
- response 200 do
165
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.index.response",
166
- default: "#{model.name} response, which include records matching current query and pagination metadata")
167
- schema do
168
- key :name, :total
169
- key :description, I18n.t('apicasso.total.description',
170
- default: 'Total records contained in current collection, as if there was no pagination.')
171
- key :required, true
172
- key :type, :integer
173
- end
174
- schema do
175
- key :name, :total_pages
176
- key :description, I18n.t('apicasso.total_pages.description',
177
- default: 'How many pages of data the current collection has.')
178
- key :required, true
179
- key :type, :integer
180
- end
181
- schema do
182
- key :name, :last_page
183
- key :description, I18n.t('apicasso.last_page.description',
184
- default: 'An indication if current request is the last to paginate in the current collection')
185
- key :required, true
186
- key :type, :boolean
187
- end
188
- schema do
189
- key :name, :previous_page
190
- key :description, I18n.t('apicasso.previous_page.description',
191
- default: "The link of the previous page for the current collection. It can be null if there isn't any")
192
- key :required, false
193
- key :type, :string
194
- end
195
- schema do
196
- key :name, :next_page
197
- key :description, I18n.t('apicasso.next_page.description',
198
- default: "The link of the next page for the current collection. It can be null if there isn't any")
199
- key :required, false
200
- key :type, :string
201
- end
202
- schema do
203
- key :name, :out_of_bounds
204
- key :description, I18n.t('apicasso.out_of_bounds.description',
205
- default: 'An indication if current request is out of pagination bounds for the current collection')
206
- key :required, true
207
- key :type, :boolean
208
- end
209
- schema do
210
- key :name, :offset
211
- key :description, I18n.t('apicasso.offset.description',
212
- default: 'How many records were offsetted from the collection to render the current page')
213
- key :required, true
214
- key :type, :integer
215
- end
216
- schema do
217
- key :name, :entries
218
- key :description, I18n.t('apicasso.entries.description',
219
- default: 'The records collection in the current pagination scope.')
220
- key :required, true
221
- key :type, :array
222
- items do
223
- key :'$ref', model.name.to_sym
224
- end
222
+ schema do
223
+ key :name, :entries
224
+ key :description, I18n.t('apicasso.entries.description',
225
+ default: 'The records collection in the current pagination scope.')
226
+ key :required, true
227
+ key :type, :array
228
+ items do
229
+ key :'$ref', model.name.to_sym
225
230
  end
226
231
  end
227
232
  end
228
- operation :options do
229
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.schema.description",
230
- default: "#{model.name} metadata information.")
231
- key :operationId, "schema#{model.name.pluralize}"
232
- key :produces, ['application/json']
233
- key :tags, [model.name.underscore]
234
- response 200 do
235
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.schema.response",
236
- default: "#{model.name} metadata as a json with field names as keys and field types as values.")
237
- schema do
238
- key :'$ref', "#{model.name}".to_sym
239
- end
233
+ end
234
+ operation :options do
235
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.schema.description",
236
+ default: "#{model.name} metadata information.")
237
+ key :operationId, "schema#{model.name.pluralize}"
238
+ key :produces, ['application/json']
239
+ key :tags, [model.name.underscore]
240
+ response 200 do
241
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.schema.response",
242
+ default: "#{model.name} metadata as a json with field names as keys and field types as values.")
243
+ schema do
244
+ key :'$ref', "#{model.name}".to_sym
240
245
  end
241
246
  end
242
- operation :post do
243
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.create.response",
244
- default: "Creates a #{model.name}")
245
- key :operationId, "add#{model.name}"
246
- key :produces, ['application/json']
247
- key :tags, [model.name.underscore]
248
- parameter do
249
- key :name, model.name.underscore.to_sym
250
- key :in, :body
251
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.create.description",
252
- default: "#{model.name} to add into application")
253
- key :required, true
254
- schema do
255
- key :'$ref', "#{model.name}".to_sym
256
- end
247
+ end
248
+ operation :post do
249
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.create.response",
250
+ default: "Creates a #{model.name}")
251
+ key :operationId, "add#{model.name}"
252
+ key :produces, ['application/json']
253
+ key :tags, [model.name.underscore]
254
+ parameter do
255
+ key :name, model.name.underscore.to_sym
256
+ key :in, :body
257
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.create.description",
258
+ default: "#{model.name} to add into application")
259
+ key :required, true
260
+ schema do
261
+ key :'$ref', "#{model.name}".to_sym
257
262
  end
258
- response 201 do
259
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
260
- default: "#{model.name} response")
261
- schema do
262
- key :'$ref', model.name.to_sym
263
- end
263
+ end
264
+ response 201 do
265
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
266
+ default: "#{model.name} response")
267
+ schema do
268
+ key :'$ref', model.name.to_sym
264
269
  end
265
270
  end
266
271
  end
267
- swagger_path "/#{model.name.underscore}/{id}" do
268
- operation :patch do
269
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.update.response",
270
- default: "Updates a #{model.name}")
271
- key :operationId, "edit#{model.name}"
272
- key :produces, ['application/json']
273
- key :tags, [model.name.underscore]
274
- parameter do
275
- key :name, :id
276
- key :in, :path
277
- key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
278
- default: "ID of #{model.name} to update on the application")
279
- key :required, true
280
- schema do
281
- key :'$ref', "#{model.name}".to_sym
282
- end
283
- end
284
- parameter do
285
- key :name, model.name.underscore.to_sym
286
- key :in, :body
287
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.update.description",
288
- default: "Existing #{model.name} to update on the application")
289
- key :required, true
290
- schema do
291
- key :'$ref', "#{model.name}".to_sym
292
- end
272
+ end
273
+ # Resource definitions of PATCH, GET, DELETE
274
+ swagger_path "/#{model.name.underscore}/{id}" do
275
+ operation :patch do
276
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.update.response",
277
+ default: "Updates a #{model.name}")
278
+ key :operationId, "edit#{model.name}"
279
+ key :produces, ['application/json']
280
+ key :tags, [model.name.underscore]
281
+ parameter do
282
+ key :name, :id
283
+ key :in, :path
284
+ key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
285
+ default: "ID of #{model.name} to update on the application")
286
+ key :required, true
287
+ schema do
288
+ key :'$ref', "#{model.name}".to_sym
293
289
  end
294
- response 200 do
295
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
296
- default: "#{model.name} response")
297
- schema do
298
- key :'$ref', model.name.to_sym
299
- end
290
+ end
291
+ parameter do
292
+ key :name, model.name.underscore.to_sym
293
+ key :in, :body
294
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.update.description",
295
+ default: "Existing #{model.name} to update on the application")
296
+ key :required, true
297
+ schema do
298
+ key :'$ref', "#{model.name}".to_sym
300
299
  end
301
300
  end
302
- operation :get do
303
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.response",
304
- default: "Creates a #{model.name}")
305
- key :operationId, "show#{model.name}"
306
- key :produces, ['application/json']
307
- key :tags, [model.name.underscore]
308
- parameter do
309
- key :name, :id
310
- key :in, :path
311
- key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
312
- default: "ID of #{model.name} to fetch on the application")
313
- key :required, true
314
- schema do
315
- key :'$ref', "#{model.name}".to_sym
316
- end
301
+ response 200 do
302
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
303
+ default: "#{model.name} response")
304
+ schema do
305
+ key :'$ref', model.name.to_sym
317
306
  end
318
- response 200 do
319
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
320
- default: "#{model.name} response")
321
- schema do
322
- key :'$ref', model.name.to_sym
323
- end
307
+ end
308
+ end
309
+ operation :get do
310
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.response",
311
+ default: "Creates a #{model.name}")
312
+ key :operationId, "show#{model.name}"
313
+ key :produces, ['application/json']
314
+ key :tags, [model.name.underscore]
315
+ parameter do
316
+ key :name, :id
317
+ key :in, :path
318
+ key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
319
+ default: "ID of #{model.name} to fetch on the application")
320
+ key :required, true
321
+ schema do
322
+ key :'$ref', "#{model.name}".to_sym
324
323
  end
325
324
  end
326
- operation :delete do
327
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.response",
328
- default: "Deletes a #{model.name}")
329
- key :operationId, "destroy#{model.name}"
330
- key :produces, ['application/json']
331
- key :tags, [model.name.underscore]
332
- parameter do
333
- key :name, :id
334
- key :in, :path
335
- key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
336
- default: "ID of #{model.name} to delete on the application")
337
- key :required, true
338
- schema do
339
- key :'$ref', "#{model.name}".to_sym
340
- end
325
+ response 200 do
326
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.show.description",
327
+ default: "#{model.name} response")
328
+ schema do
329
+ key :'$ref', model.name.to_sym
341
330
  end
342
- response 200 do
343
- key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.description",
344
- default: "#{model.name} response")
331
+ end
332
+ end
333
+ operation :delete do
334
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.response",
335
+ default: "Deletes a #{model.name}")
336
+ key :operationId, "destroy#{model.name}"
337
+ key :produces, ['application/json']
338
+ key :tags, [model.name.underscore]
339
+ parameter do
340
+ key :name, :id
341
+ key :in, :path
342
+ key :description, I18n.t("activerecord.models.attributes.#{model.name.underscore}.id",
343
+ default: "ID of #{model.name} to delete on the application")
344
+ key :required, true
345
+ schema do
346
+ key :'$ref', "#{model.name}".to_sym
345
347
  end
346
348
  end
349
+ response 200 do
350
+ key :description, I18n.t("activerecord.models.#{model.name.underscore}.destroy.description",
351
+ default: "#{model.name} response")
352
+ end
347
353
  end
348
-
349
- model.reflect_on_all_associations.map(&:name).each do |association|
350
- inner_name = association.to_s.classify
351
- unless ASSOCIATION_EXCLUDED.include?(inner_name)
352
- inner_klass = begin inner_name.constantize rescue NameError; false end
353
- swagger_path "/#{model.name.underscore}/{id}/#{association}" do
354
- operation :get do
355
- key :summary, I18n.t("activerecord.models.#{inner_name.underscore}.index.summary", default: inner_name)
356
- key :description, I18n.t("activerecord.models.#{inner_name.underscore}.index.description", default: inner_name)
357
- key :operationId, "find#{inner_name.pluralize}"
358
- key :produces, ['application/json']
359
- key :tags, [inner_name.underscore]
360
- parameter do
361
- key :name, :sort
362
- key :in, :query
363
- key :description, I18n.t('apicasso.sort.description',
364
- default: 'Parameters sorting splitted by `,` preffixed by `+` or `-` which translates into ascending or descending order')
354
+ end
355
+ # Resource's associations definitions
356
+ model.reflect_on_all_associations.map(&:name).each do |association|
357
+ inner_name = association.to_s.classify
358
+ unless ASSOCIATION_EXCLUDED.include?(inner_name)
359
+ inner_klass = begin inner_name.constantize rescue NameError; false end
360
+ swagger_path "/#{model.name.underscore}/{id}/#{association}" do
361
+ operation :get do
362
+ key :summary, I18n.t("activerecord.models.#{inner_name.underscore}.index.summary", default: inner_name)
363
+ key :description, I18n.t("activerecord.models.#{inner_name.underscore}.index.description", default: inner_name)
364
+ key :operationId, "find#{inner_name.pluralize}"
365
+ key :produces, ['application/json']
366
+ key :tags, [inner_name.underscore]
367
+ parameter do
368
+ key :name, :sort
369
+ key :in, :query
370
+ key :description, I18n.t('apicasso.sort.description',
371
+ default: 'Parameters sorting splitted by `,` preffixed by `+` or `-` which translates into ascending or descending order')
372
+ key :required, false
373
+ key :type, :string
374
+ key :collectionFormat, :json
375
+ end
376
+ parameter do
377
+ key :name, :q
378
+ key :in, :query
379
+ key :description, I18n.t('apicasso.q.description',
380
+ default: 'Records filtering by attribute and search query as affix. Usage: `?q[{attribute}{search_affix}]={matcher}`. All available search affixes are listed on: https://github.com/activerecord-hackery/ransack#search-matchers')
381
+ key :required, false
382
+ key :type, :json
383
+ end
384
+ parameter do
385
+ key :name, :page
386
+ key :in, :query
387
+ key :description, I18n.t('apicasso.page.description',
388
+ default: 'Records pagination paging, which offsets collection based on `params[:per_page]`')
389
+ key :required, false
390
+ key :type, :integer
391
+ end
392
+ parameter do
393
+ key :name, :per_page
394
+ key :in, :query
395
+ key :description, I18n.t('apicasso.per_page.description',
396
+ default: 'Records pagination size, which sets how many records will be rendered per request')
397
+ key :required, false
398
+ key :type, :integer
399
+ end
400
+ response 200 do
401
+ key :description, I18n.t("activerecord.models.#{inner_name.underscore}.index.response",
402
+ default: "#{inner_name} response, which include records matching current query and pagination metadata")
403
+ schema do
404
+ key :name, :total
405
+ key :description, I18n.t('apicasso.total.description',
406
+ default: 'Total records contained in current collection, as if there was no pagination.')
407
+ key :required, true
408
+ key :type, :integer
409
+ end
410
+ schema do
411
+ key :name, :total_pages
412
+ key :description, I18n.t('apicasso.total_pages.description',
413
+ default: 'How many pages of data the current collection has.')
414
+ key :required, true
415
+ key :type, :integer
416
+ end
417
+ schema do
418
+ key :name, :last_page
419
+ key :description, I18n.t('apicasso.last_page.description',
420
+ default: 'An indication if current request is the last to paginate in the current collection')
421
+ key :required, true
422
+ key :type, :boolean
423
+ end
424
+ schema do
425
+ key :name, :previous_page
426
+ key :description, I18n.t('apicasso.previous_page.description',
427
+ default: "The link of the previous page for the current collection. It can be null if there isn't any")
365
428
  key :required, false
366
429
  key :type, :string
367
- key :collectionFormat, :json
368
430
  end
369
- parameter do
370
- key :name, :q
371
- key :in, :query
372
- key :description, I18n.t('apicasso.q.description',
373
- default: 'Records filtering by attribute and search query as affix. Usage: `?q[{attribute}{search_affix}]={matcher}`. All available search affixes are listed on: https://github.com/activerecord-hackery/ransack#search-matchers')
431
+ schema do
432
+ key :name, :next_page
433
+ key :description, I18n.t('apicasso.next_page.description',
434
+ default: "The link of the next page for the current collection. It can be null if there isn't any")
374
435
  key :required, false
375
- key :type, :json
436
+ key :type, :string
376
437
  end
377
- parameter do
378
- key :name, :page
379
- key :in, :query
380
- key :description, I18n.t('apicasso.page.description',
381
- default: 'Records pagination paging, which offsets collection based on `params[:per_page]`')
382
- key :required, false
383
- key :type, :integer
438
+ schema do
439
+ key :name, :out_of_bounds
440
+ key :description, I18n.t('apicasso.out_of_bounds.description',
441
+ default: 'An indication if current request is out of pagination bounds for the current collection')
442
+ key :required, true
443
+ key :type, :boolean
384
444
  end
385
- parameter do
386
- key :name, :per_page
387
- key :in, :query
388
- key :description, I18n.t('apicasso.per_page.description',
389
- default: 'Records pagination size, which sets how many records will be rendered per request')
390
- key :required, false
445
+ schema do
446
+ key :name, :offset
447
+ key :description, I18n.t('apicasso.offset.description',
448
+ default: 'How many records were offsetted from the collection to render the current page')
449
+ key :required, true
391
450
  key :type, :integer
392
451
  end
393
- response 200 do
394
- key :description, I18n.t("activerecord.models.#{inner_name.underscore}.index.response",
395
- default: "#{inner_name} response, which include records matching current query and pagination metadata")
396
- schema do
397
- key :name, :total
398
- key :description, I18n.t('apicasso.total.description',
399
- default: 'Total records contained in current collection, as if there was no pagination.')
400
- key :required, true
401
- key :type, :integer
402
- end
403
- schema do
404
- key :name, :total_pages
405
- key :description, I18n.t('apicasso.total_pages.description',
406
- default: 'How many pages of data the current collection has.')
407
- key :required, true
408
- key :type, :integer
409
- end
410
- schema do
411
- key :name, :last_page
412
- key :description, I18n.t('apicasso.last_page.description',
413
- default: 'An indication if current request is the last to paginate in the current collection')
414
- key :required, true
415
- key :type, :boolean
416
- end
417
- schema do
418
- key :name, :previous_page
419
- key :description, I18n.t('apicasso.previous_page.description',
420
- default: "The link of the previous page for the current collection. It can be null if there isn't any")
421
- key :required, false
422
- key :type, :string
423
- end
424
- schema do
425
- key :name, :next_page
426
- key :description, I18n.t('apicasso.next_page.description',
427
- default: "The link of the next page for the current collection. It can be null if there isn't any")
428
- key :required, false
429
- key :type, :string
430
- end
431
- schema do
432
- key :name, :out_of_bounds
433
- key :description, I18n.t('apicasso.out_of_bounds.description',
434
- default: 'An indication if current request is out of pagination bounds for the current collection')
435
- key :required, true
436
- key :type, :boolean
437
- end
438
- schema do
439
- key :name, :offset
440
- key :description, I18n.t('apicasso.offset.description',
441
- default: 'How many records were offsetted from the collection to render the current page')
442
- key :required, true
443
- key :type, :integer
444
- end
445
- schema do
446
- key :name, :entries
447
- key :description, I18n.t('apicasso.entries.description',
448
- default: 'The records collection in the current pagination scope.')
449
- key :required, true
450
- key :type, :array
451
- items do
452
- key :'$ref', "#{inner_name}".to_sym
453
- end
452
+ schema do
453
+ key :name, :entries
454
+ key :description, I18n.t('apicasso.entries.description',
455
+ default: 'The records collection in the current pagination scope.')
456
+ key :required, true
457
+ key :type, :array
458
+ items do
459
+ key :'$ref', "#{inner_name}".to_sym
454
460
  end
455
461
  end
456
- response :default do
457
- key :description, I18n.t("activerecord.errors.models.#{inner_name.underscore}",
458
- default: "Unexpected error in #{inner_name}")
459
- schema do
460
- key :'$ref', :ErrorModel
461
- end
462
+ end
463
+ response :default do
464
+ key :description, I18n.t("activerecord.errors.models.#{inner_name.underscore}",
465
+ default: "Unexpected error in #{inner_name}")
466
+ schema do
467
+ key :'$ref', :ErrorModel
462
468
  end
463
469
  end
464
- operation :options do
465
- key :description, I18n.t("activerecord.models.#{inner_name.underscore}.schema.description",
466
- default: "#{inner_name} metadata information.")
467
- key :operationId, "schema#{inner_name.pluralize}"
468
- key :produces, ['application/json']
469
- key :tags, [inner_name.underscore]
470
- response 200 do
471
- key :description, I18n.t("activerecord.models.#{inner_name.underscore}.schema.response",
472
- default: "#{inner_name} metadata as a json with field names as keys and field types as values.")
473
- schema do
474
- key :'$ref', "#{inner_name}".to_sym
475
- end
470
+ end
471
+ operation :options do
472
+ key :description, I18n.t("activerecord.models.#{inner_name.underscore}.schema.description",
473
+ default: "#{inner_name} metadata information.")
474
+ key :operationId, "schema#{inner_name.pluralize}"
475
+ key :produces, ['application/json']
476
+ key :tags, [inner_name.underscore]
477
+ response 200 do
478
+ key :description, I18n.t("activerecord.models.#{inner_name.underscore}.schema.response",
479
+ default: "#{inner_name} metadata as a json with field names as keys and field types as values.")
480
+ schema do
481
+ key :'$ref', "#{inner_name}".to_sym
476
482
  end
477
- response :default do
478
- key :description, I18n.t("activerecord.errors.models.#{inner_name.underscore}",
479
- default: "Unexpected error in #{inner_name}")
480
- schema do
481
- key :'$ref', :ErrorModel
482
- end
483
+ end
484
+ response :default do
485
+ key :description, I18n.t("activerecord.errors.models.#{inner_name.underscore}",
486
+ default: "Unexpected error in #{inner_name}")
487
+ schema do
488
+ key :'$ref', :ErrorModel
483
489
  end
484
490
  end
485
491
  end
486
492
  end
487
493
  end
488
494
  end
489
-
495
+ # Method that serves the generated Swagger JSON
490
496
  def index
491
497
  render json: Swagger::Blocks.build_root_json(SWAGGERED_CLASSES).to_json
492
498
  end
493
499
  end
494
- end
500
+ end