praxis 2.0.pre.29 → 2.0.pre.30

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +24 -0
  5. data/SELECTOR_NOTES.txt +0 -0
  6. data/lib/praxis/application.rb +4 -0
  7. data/lib/praxis/blueprint.rb +13 -1
  8. data/lib/praxis/blueprint_attribute_group.rb +29 -0
  9. data/lib/praxis/docs/open_api/schema_object.rb +8 -7
  10. data/lib/praxis/endpoint_definition.rb +1 -1
  11. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +11 -11
  12. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +0 -1
  13. data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +1 -1
  14. data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +54 -4
  15. data/lib/praxis/extensions/pagination/ordering_params.rb +38 -10
  16. data/lib/praxis/extensions/pagination/pagination_handler.rb +3 -3
  17. data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +1 -1
  18. data/lib/praxis/mapper/resource.rb +155 -14
  19. data/lib/praxis/mapper/selector_generator.rb +248 -46
  20. data/lib/praxis/media_type_identifier.rb +1 -1
  21. data/lib/praxis/multipart/part.rb +2 -2
  22. data/lib/praxis/plugins/mapper_plugin.rb +4 -3
  23. data/lib/praxis/renderer.rb +1 -1
  24. data/lib/praxis/routing_config.rb +1 -1
  25. data/lib/praxis/tasks/console.rb +21 -26
  26. data/lib/praxis/types/multipart_array.rb +1 -1
  27. data/lib/praxis/version.rb +1 -1
  28. data/lib/praxis.rb +1 -0
  29. data/praxis.gemspec +1 -1
  30. data/spec/functional_library_spec.rb +187 -0
  31. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +11 -1
  32. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +16 -4
  33. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +0 -2
  34. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +0 -2
  35. data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +111 -25
  36. data/spec/praxis/extensions/pagination/ordering_params_spec.rb +70 -0
  37. data/spec/praxis/mapper/resource_spec.rb +40 -4
  38. data/spec/praxis/mapper/selector_generator_spec.rb +979 -296
  39. data/spec/praxis/request_stages/action_spec.rb +1 -1
  40. data/spec/spec_app/app/controllers/authors.rb +37 -0
  41. data/spec/spec_app/app/controllers/books.rb +31 -0
  42. data/spec/spec_app/app/resources/author.rb +21 -0
  43. data/spec/spec_app/app/resources/base.rb +14 -0
  44. data/spec/spec_app/app/resources/book.rb +43 -0
  45. data/spec/spec_app/app/resources/tag.rb +9 -0
  46. data/spec/spec_app/app/resources/tagging.rb +9 -0
  47. data/spec/spec_app/config/environment.rb +16 -1
  48. data/spec/spec_app/design/media_types/author.rb +13 -0
  49. data/spec/spec_app/design/media_types/book.rb +22 -0
  50. data/spec/spec_app/design/media_types/tag.rb +11 -0
  51. data/spec/spec_app/design/media_types/tagging.rb +10 -0
  52. data/spec/spec_app/design/resources/authors.rb +35 -0
  53. data/spec/spec_app/design/resources/books.rb +39 -0
  54. data/spec/spec_helper.rb +0 -1
  55. data/spec/support/spec_resources.rb +20 -7
  56. data/spec/{praxis/extensions/support → support}/spec_resources_active_model.rb +14 -0
  57. metadata +24 -7
  58. /data/spec/{functional_spec.rb → functional_cloud_spec.rb} +0 -0
  59. /data/spec/{praxis/extensions/support → support}/spec_resources_sequel.rb +0 -0
@@ -26,7 +26,7 @@ describe Praxis::RequestStages::Action do
26
26
 
27
27
  context '.execute' do
28
28
  before do
29
- expect(controller).to receive(action_stage.name) do |args|
29
+ expect(controller).to receive(action_stage.name) do |**args|
30
30
  if args
31
31
  expect(args).to eq({})
32
32
  else
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_class'
4
+
5
+ class Authors < BaseClass
6
+ include Praxis::Controller
7
+
8
+ implements ApiResources::Authors
9
+ include Praxis::Extensions::Rendering
10
+
11
+ def model_class
12
+ ActiveAuthor
13
+ end
14
+
15
+ def base_query
16
+ # Artificially set a base query that has joins, including a join against the base authors table (to test aliasing)
17
+ # Note: in order to make sure we know what table name to refer to, we need to add our special reference (based on path)
18
+ # This way, regardles of filters and/or ordering potentially being applied, we will always point to the correct alias
19
+ books_ref = Praxis::Extensions::AttributeFiltering::ActiveRecordFilterQueryBuilder.build_reference_value('/books', query: model_class)
20
+ inner_authors_ref = Praxis::Extensions::AttributeFiltering::ActiveRecordFilterQueryBuilder.build_reference_value('/books/author', query: model_class)
21
+ model_class.distinct.joins(books: :author)
22
+ .references(books_ref).where('"/books".simple_name LIKE ?', 'book%')
23
+ .references(inner_authors_ref).where("#{inner_authors_ref}.id > ?", 0)
24
+ end
25
+
26
+ def index
27
+ objs = build_query(base_query).all
28
+ display(objs)
29
+ end
30
+
31
+ def show(id:, **_args)
32
+ model = build_query(base_query.where(id: id)).first
33
+ return Praxis::Mapper::ResourceNotFound.new(id: id, type: model_class) if model.nil?
34
+
35
+ display(model)
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Books < BaseClass
4
+ include Praxis::Controller
5
+
6
+ implements ApiResources::Books
7
+ include Praxis::Extensions::Rendering
8
+
9
+ def model_class
10
+ ActiveBook
11
+ end
12
+
13
+ def base_query
14
+ # Make sure we add the distinct clause, that's what we always want for index requests
15
+ # as we can have multiple copies of the same top level model if there were joins due
16
+ # to manual conditions added, or simply conditions added when filters are used on related tables
17
+ model_class.distinct
18
+ end
19
+
20
+ def index
21
+ objs = build_query(base_query).all
22
+ display(objs)
23
+ end
24
+
25
+ def show(id:, **_args)
26
+ model = build_query(base_query.where(id: id)).first
27
+ return Praxis::Mapper::ResourceNotFound.new(id: id, type: model_class) if model.nil?
28
+
29
+ display(model)
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Resources
6
+ class Author < Resources::Base
7
+ model ::ActiveAuthor
8
+
9
+ filters_mapping(
10
+ 'books.name': 'books.name'
11
+ )
12
+ order_mapping(
13
+ 'display_name': 'name'
14
+ )
15
+ property :display_name, dependencies: [:name]
16
+
17
+ def display_name
18
+ record.name
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resources
4
+ class Base < Praxis::Mapper::Resource
5
+ include Praxis::Mapper::Resources::QueryMethods # So we can directly get wrapped models with get, all, first, last...
6
+
7
+ def self.inherited(klass)
8
+ klass.include Praxis::Mapper::Resources::Callbacks # So we can use callbacks (after/before/around) within resource code
9
+ # Add the code that allows to define typed method signatures (to be validated and coerced) to the concrete class
10
+ klass.include Praxis::Mapper::Resources::TypedMethods
11
+ super
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Resources
6
+ class Book < Resources::Base
7
+ model ::ActiveBook
8
+
9
+ filters_mapping(
10
+ name: :simple_name
11
+ )
12
+
13
+ order_mapping(
14
+ name: 'simple_name',
15
+ writer: 'author'
16
+ )
17
+
18
+ # Make name go through another nested property, before getting to simple_name
19
+ property :name, dependencies: [:nested_name]
20
+ def name
21
+ nested_name
22
+ end
23
+
24
+ property :nested_name, dependencies: [:simple_name]
25
+ def nested_name
26
+ record.simple_name
27
+ end
28
+
29
+ property_group :grouped, ::Book
30
+
31
+ property :grouped_id, dependencies: [:id]
32
+ def grouped_id
33
+ id
34
+ end
35
+
36
+ property :grouped_name, dependencies: [:name]
37
+ def grouped_name
38
+ name
39
+ end
40
+
41
+ property :grouped_moar_tags, as: :tags
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Resources
6
+ class Tag < Resources::Base
7
+ model ::ActiveTag
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Resources
6
+ class Tagging < Resources::Base
7
+ model ::ActiveTagging
8
+ end
9
+ end
@@ -33,7 +33,18 @@ Praxis::Application.configure do |application|
33
33
 
34
34
  application.bootloader.use SimpleAuthenticationPlugin, config_file: 'config/authentication.yml'
35
35
  application.bootloader.use AuthorizationPlugin
36
-
36
+ application.bootloader.use Praxis::Plugins::MapperPlugin
37
+ application.bootloader.use Praxis::Plugins::PaginationPlugin,
38
+ **{
39
+ # max_items: 500, # Unlimited by default,
40
+ # default_page_size: 100,
41
+ # paging_default_mode: {by: :id},
42
+ # disallow_paging_by_default: false,
43
+ # disallow_cursor_by_default: false,
44
+ # sorting: {
45
+ # enforce_all_fields: true
46
+ # }
47
+ }
37
48
  # enable "development-mode" options
38
49
  application.config.praxis.validate_responses = true
39
50
  application.config.praxis.validate_response_bodies = true
@@ -44,6 +55,9 @@ Praxis::Application.configure do |application|
44
55
  LowBudgetMutex.instance.after_app_controllers_called
45
56
  end
46
57
  application.bootloader.after :app do
58
+ # application.config.mapper.debug_queries = true # Enable this to see debug info about the query builder and plan
59
+
60
+ Praxis::Mapper::Resource.finalize!
47
61
  raise 'After sub-stage hooks not working!' unless LowBudgetMutex.instance.after_app_controllers == :worked
48
62
  end
49
63
 
@@ -58,6 +72,7 @@ Praxis::Application.configure do |application|
58
72
  map :app, 'app/' do
59
73
  map :models, 'models/**/*'
60
74
  map :concerns, '**/concerns/**/*'
75
+ map :resources, '**/resources/**/*'
61
76
  map :controllers, '**/controllers/**/*'
62
77
  map :responses, '**/responses/**/*'
63
78
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Author < Praxis::MediaType
4
+ identifier 'application/vnd.acme.author'
5
+
6
+ domain_model 'Resources::Author'
7
+ attributes do
8
+ attribute :id, Integer
9
+ attribute :name, String
10
+ attribute :display_name, String
11
+ attribute :books, Praxis::Collection.of(Book)
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Book < Praxis::MediaType
4
+ identifier 'application/vnd.acme.book'
5
+
6
+ domain_model 'Resources::Book'
7
+
8
+ attributes do
9
+ attribute :id, Integer
10
+ attribute :name, String
11
+ attribute :simple_name, String
12
+ attribute :category_uuid, String
13
+ attribute :author, Author
14
+ attribute :tags, Praxis::Collection.of(Tag)
15
+
16
+ group :grouped do
17
+ attribute :id
18
+ attribute :name
19
+ attribute :moar_tags, Praxis::Collection.of(Tag)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tag < Praxis::MediaType
4
+ identifier 'application/vnd.acme.tag'
5
+
6
+ domain_model 'Resources::Tag'
7
+ attributes do
8
+ attribute :name, String
9
+ attribute :taggings, Praxis::Collection.of(Tagging)
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tagging < Praxis::MediaType
4
+ identifier 'application/vnd.acme.tagging'
5
+
6
+ domain_model 'Resources::Tagging'
7
+ attributes do
8
+ attribute :tag, Tag
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiResources
4
+ class Authors
5
+ include Praxis::EndpointDefinition
6
+
7
+ media_type Author
8
+ version '1.0'
9
+
10
+ action :index do
11
+ routing { get '' }
12
+ params do
13
+ attribute :fields, Praxis::Types::FieldSelector.for(Author), description: 'Fields with which to render the result.'
14
+ attribute :filters, Praxis::Types::FilteringParams.for(Author) do
15
+ filter 'books.name', using: %w[= != !], fuzzy: true
16
+ filter 'id', using: %w[= !=]
17
+ end
18
+ attribute :order, Praxis::Extensions::Pagination::OrderingParams.for(Author) do
19
+ by_fields :id, :name, 'books.name'
20
+ end
21
+ end
22
+ response :ok, media_type: Praxis::Collection.of(Author)
23
+ end
24
+
25
+ action :show do
26
+ routing { get '/:id' }
27
+
28
+ params do
29
+ attribute :id, description: 'ID to find'
30
+ attribute :fields, Praxis::Types::FieldSelector.for(Author), description: 'Fields with which to render the result.'
31
+ end
32
+ response :ok
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiResources
4
+ class Books
5
+ include Praxis::EndpointDefinition
6
+
7
+ media_type Book
8
+ version '1.0'
9
+
10
+ action :index do
11
+ routing { get '' }
12
+ params do
13
+ attribute :fields, Praxis::Types::FieldSelector.for(Book), description: 'Fields with which to render the result.'
14
+ attribute :filters, Praxis::Types::FilteringParams.for(Book) do
15
+ filter 'author.name', using: %w[= != !], fuzzy: true
16
+ filter 'author', using: %w[! !!]
17
+ filter 'tags.name', using: %w[= !=]
18
+ filter 'author.id', using: %w[= !=]
19
+ filter 'id', using: %w[= !=]
20
+ filter 'tags.taggings.tag.name', using: %w[= !=]
21
+ end
22
+ attribute :order, Praxis::Extensions::Pagination::OrderingParams.for(Book) do
23
+ by_fields :id, 'author.name'
24
+ end
25
+ end
26
+ response :ok, media_type: Praxis::Collection.of(Book)
27
+ end
28
+
29
+ action :show do
30
+ routing { get '/:id' }
31
+
32
+ params do
33
+ attribute :id, description: 'ID to find'
34
+ attribute :fields, Praxis::Types::FieldSelector.for(Book), description: 'Fields with which to render the result.'
35
+ end
36
+ response :ok
37
+ end
38
+ end
39
+ end
data/spec/spec_helper.rb CHANGED
@@ -48,7 +48,6 @@ RSpec.configure do |config|
48
48
  config.include Rack::Test::Methods
49
49
 
50
50
  config.before(:suite) do
51
- Praxis::Mapper::Resource.finalize!
52
51
  Praxis::Blueprint.caching_enabled = true
53
52
  Praxis::Application.instance.setup(root: 'spec/spec_app')
54
53
  end
@@ -103,6 +103,7 @@ class ParentResource < BaseResource
103
103
  model ParentModel
104
104
 
105
105
  property :display_name, dependencies: %i[simple_name id other_attribute]
106
+ property :aliased_simple_children, as: :simple_children
106
107
 
107
108
  def display_name
108
109
  "#{id}-#{name}"
@@ -137,12 +138,14 @@ class SimpleResource < BaseResource
137
138
  end
138
139
  end
139
140
 
141
+ property :multi_column, dependencies: %i[column1 simple_name]
140
142
  property :aliased_method, dependencies: %i[column1 other_model]
141
143
  property :other_resource, dependencies: [:other_model]
142
-
143
144
  property :parent, dependencies: %i[parent added_column]
144
145
 
145
- property :name, dependencies: [:simple_name]
146
+ property :name, dependencies: [:nested_name]
147
+ property :nested_name, dependencies: [:simple_name]
148
+
146
149
  property :direct_other_name, dependencies: ['other_model.name']
147
150
  property :aliased_other_name, dependencies: ['other_model.display_name']
148
151
 
@@ -150,13 +153,23 @@ class SimpleResource < BaseResource
150
153
  property :everything_from_parent, dependencies: ['parent.*']
151
154
  property :circular_dep, dependencies: %i[circular_dep column1]
152
155
  property :no_deps, dependencies: []
153
-
154
156
  property :deep_nested_deps, dependencies: ['parent.simple_children.other_model.parent.display_name']
155
- property :aliased_association, as: :other_model, dependencies: [:name]
156
- property :overriden_aliased_association, as: :other_model, dependencies: [:name]
157
- property :deep_aliased_association, as: 'parent.simple_children' , dependencies: [:name]
158
157
 
159
- property :sub_struct, as: :self, dependencies: [:alway_necessary_attribute]
158
+ property :aliased_association, as: :other_model
159
+ property :deep_aliased_association, as: 'parent.simple_children'
160
+ property :overriden_aliased_association, as: :other_model
161
+ property :aliased_parent, as: :parent
162
+ property :deep_overriden_aliased_association, as: 'parent.simple_children' # TODO!!! if I change it to 'aliased_parent.aliased_simple_children' things come empty!!!
163
+ property :sub_struct, as: :self
164
+
165
+ property :true_struct, dependencies: %i[name sub_id]
166
+ # property :true_struct, dependencies: [:sub_id]
167
+ property :sub_id, dependencies: [:inner_sub_id]
168
+ property :inner_sub_id, dependencies: [:id]
169
+
170
+ property :agroup, dependencies: %i[agroup_id agroup_name]
171
+ property :agroup_id, dependencies: [:id]
172
+ property :agroup_name, dependencies: [:name]
160
173
 
161
174
  before(:update!, :do_before_update)
162
175
  around(:update!, :do_around_update_nested)
@@ -87,6 +87,9 @@ end
87
87
  class ActiveAuthorResource < ActiveBaseResource
88
88
  model ActiveAuthor
89
89
 
90
+ order_mapping(
91
+ 'display_name': 'name'
92
+ )
90
93
  property :display_name, dependencies: [:name]
91
94
  end
92
95
 
@@ -109,11 +112,22 @@ class ActiveBookResource < ActiveBaseResource
109
112
  end,
110
113
  'category.books.name': 'category.books.simple_name'
111
114
  )
115
+
116
+ order_mapping(
117
+ 'name': 'simple_name',
118
+ 'writer': 'author'
119
+ )
112
120
  # Forces to add an extra column (added_column)...and yet another (author_id) that will serve
113
121
  # to check that if that's already automatically added due to an association, it won't interfere or duplicate
114
122
  property :author, dependencies: %i[author added_column author_id]
115
123
 
116
124
  property :name, dependencies: [:simple_name]
125
+ property :writer, dependencies: %i[author]
126
+
127
+ # Silly alias to test dependencies and order aliasing
128
+ def writer
129
+ author
130
+ end
117
131
  end
118
132
 
119
133
  def seed_data
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: praxis
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.pre.29
4
+ version: 2.0.pre.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josep M. Blanquer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-01-24 00:00:00.000000000 Z
12
+ date: 2023-03-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -376,6 +376,7 @@ files:
376
376
  - MAINTAINERS.md
377
377
  - README.md
378
378
  - Rakefile
379
+ - SELECTOR_NOTES.txt
379
380
  - bin/praxis
380
381
  - lib/praxis.rb
381
382
  - lib/praxis/action_definition.rb
@@ -384,6 +385,7 @@ files:
384
385
  - lib/praxis/api_general_info.rb
385
386
  - lib/praxis/application.rb
386
387
  - lib/praxis/blueprint.rb
388
+ - lib/praxis/blueprint_attribute_group.rb
387
389
  - lib/praxis/bootloader.rb
388
390
  - lib/praxis/bootloader_stages/environment.rb
389
391
  - lib/praxis/bootloader_stages/file_loader.rb
@@ -512,7 +514,8 @@ files:
512
514
  - lib/praxis/validation_handler.rb
513
515
  - lib/praxis/version.rb
514
516
  - praxis.gemspec
515
- - spec/functional_spec.rb
517
+ - spec/functional_cloud_spec.rb
518
+ - spec/functional_library_spec.rb
516
519
  - spec/praxis/action_definition_spec.rb
517
520
  - spec/praxis/api_definition_spec.rb
518
521
  - spec/praxis/api_general_info_spec.rb
@@ -534,9 +537,8 @@ files:
534
537
  - spec/praxis/extensions/field_selection/field_selector_spec.rb
535
538
  - spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb
536
539
  - spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb
540
+ - spec/praxis/extensions/pagination/ordering_params_spec.rb
537
541
  - spec/praxis/extensions/rendering_spec.rb
538
- - spec/praxis/extensions/support/spec_resources_active_model.rb
539
- - spec/praxis/extensions/support/spec_resources_sequel.rb
540
542
  - spec/praxis/field_expander_spec.rb
541
543
  - spec/praxis/file_group_spec.rb
542
544
  - spec/praxis/handlers/json_spec.rb
@@ -571,9 +573,16 @@ files:
571
573
  - spec/spec_app/app/concerns/authenticated.rb
572
574
  - spec/spec_app/app/concerns/basic_api.rb
573
575
  - spec/spec_app/app/concerns/log_wrapper.rb
576
+ - spec/spec_app/app/controllers/authors.rb
574
577
  - spec/spec_app/app/controllers/base_class.rb
578
+ - spec/spec_app/app/controllers/books.rb
575
579
  - spec/spec_app/app/controllers/instances.rb
576
580
  - spec/spec_app/app/controllers/volumes.rb
581
+ - spec/spec_app/app/resources/author.rb
582
+ - spec/spec_app/app/resources/base.rb
583
+ - spec/spec_app/app/resources/book.rb
584
+ - spec/spec_app/app/resources/tag.rb
585
+ - spec/spec_app/app/resources/tagging.rb
577
586
  - spec/spec_app/app/responses/multipart.rb
578
587
  - spec/spec_app/app/responses/other_response.rb
579
588
  - spec/spec_app/config.ru
@@ -587,9 +596,15 @@ files:
587
596
  - spec/spec_app/config/stats.yml
588
597
  - spec/spec_app/config/stats.yml.dis
589
598
  - spec/spec_app/design/api.rb
599
+ - spec/spec_app/design/media_types/author.rb
600
+ - spec/spec_app/design/media_types/book.rb
590
601
  - spec/spec_app/design/media_types/instance.rb
602
+ - spec/spec_app/design/media_types/tag.rb
603
+ - spec/spec_app/design/media_types/tagging.rb
591
604
  - spec/spec_app/design/media_types/volume.rb
592
605
  - spec/spec_app/design/media_types/volume_snapshot.rb
606
+ - spec/spec_app/design/resources/authors.rb
607
+ - spec/spec_app/design/resources/books.rb
593
608
  - spec/spec_app/design/resources/instances.rb
594
609
  - spec/spec_app/design/resources/volume_snapshots.rb
595
610
  - spec/spec_app/design/resources/volumes.rb
@@ -601,6 +616,8 @@ files:
601
616
  - spec/support/spec_endpoint_definitions.rb
602
617
  - spec/support/spec_media_types.rb
603
618
  - spec/support/spec_resources.rb
619
+ - spec/support/spec_resources_active_model.rb
620
+ - spec/support/spec_resources_sequel.rb
604
621
  - spec/support/spec_simple_authentication_plugin.rb
605
622
  - tasks/loader.thor
606
623
  - tasks/thor/app.rb
@@ -669,14 +686,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
669
686
  requirements:
670
687
  - - ">="
671
688
  - !ruby/object:Gem::Version
672
- version: '2.5'
689
+ version: '2.7'
673
690
  required_rubygems_version: !ruby/object:Gem::Requirement
674
691
  requirements:
675
692
  - - ">"
676
693
  - !ruby/object:Gem::Version
677
694
  version: 1.3.1
678
695
  requirements: []
679
- rubygems_version: 3.3.7
696
+ rubygems_version: 3.1.2
680
697
  signing_key:
681
698
  specification_version: 4
682
699
  summary: Building APIs the way you want it.