apicasso 0.4.11 → 0.5.0

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