praxis 2.0.pre.10 → 2.0.pre.15
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +1 -3
- data/CHANGELOG.md +26 -0
- data/bin/praxis +65 -2
- data/lib/praxis/api_definition.rb +8 -4
- data/lib/praxis/bootloader_stages/environment.rb +1 -0
- data/lib/praxis/collection.rb +11 -0
- data/lib/praxis/docs/open_api/response_object.rb +21 -6
- data/lib/praxis/docs/open_api_generator.rb +1 -1
- data/lib/praxis/extensions/attribute_filtering.rb +14 -1
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +206 -66
- data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +3 -2
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +45 -41
- data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +193 -0
- data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +20 -8
- data/lib/praxis/extensions/pagination.rb +5 -32
- data/lib/praxis/mapper/active_model_compat.rb +4 -0
- data/lib/praxis/mapper/resource.rb +18 -2
- data/lib/praxis/mapper/selector_generator.rb +1 -0
- data/lib/praxis/mapper/sequel_compat.rb +7 -0
- data/lib/praxis/media_type_identifier.rb +11 -1
- data/lib/praxis/plugins/mapper_plugin.rb +22 -13
- data/lib/praxis/plugins/pagination_plugin.rb +34 -4
- data/lib/praxis/response_definition.rb +46 -66
- data/lib/praxis/responses/http.rb +3 -1
- data/lib/praxis/tasks/api_docs.rb +4 -1
- data/lib/praxis/tasks/routes.rb +6 -6
- data/lib/praxis/version.rb +1 -1
- data/spec/praxis/action_definition_spec.rb +3 -1
- data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +267 -167
- data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +25 -6
- data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +100 -17
- data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +148 -0
- data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +1 -1
- data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +1 -1
- data/spec/praxis/extensions/support/spec_resources_active_model.rb +1 -1
- data/spec/praxis/mapper/selector_generator_spec.rb +1 -1
- data/spec/praxis/media_type_identifier_spec.rb +15 -1
- data/spec/praxis/response_definition_spec.rb +37 -129
- data/tasks/thor/example.rb +12 -6
- data/tasks/thor/model.rb +40 -0
- data/tasks/thor/scaffold.rb +117 -0
- data/tasks/thor/templates/generator/empty_app/config/environment.rb +1 -0
- data/tasks/thor/templates/generator/example_app/Rakefile +9 -2
- data/tasks/thor/templates/generator/example_app/app/v1/concerns/controller_base.rb +24 -0
- data/tasks/thor/templates/generator/example_app/app/v1/concerns/href.rb +33 -0
- data/tasks/thor/templates/generator/example_app/app/v1/controllers/users.rb +2 -2
- data/tasks/thor/templates/generator/example_app/app/v1/resources/base.rb +15 -0
- data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +7 -28
- data/tasks/thor/templates/generator/example_app/config.ru +1 -2
- data/tasks/thor/templates/generator/example_app/config/environment.rb +3 -2
- data/tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb +3 -2
- data/tasks/thor/templates/generator/example_app/db/seeds.rb +6 -0
- data/tasks/thor/templates/generator/example_app/design/v1/endpoints/users.rb +4 -4
- data/tasks/thor/templates/generator/example_app/design/v1/media_types/user.rb +1 -6
- data/tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb +4 -2
- data/tasks/thor/templates/generator/example_app/spec/spec_helper.rb +2 -2
- data/tasks/thor/templates/generator/example_app/spec/v1/controllers/users_spec.rb +2 -2
- data/tasks/thor/templates/generator/scaffold/design/endpoints/collection.rb +98 -0
- data/tasks/thor/templates/generator/scaffold/design/media_types/item.rb +18 -0
- data/tasks/thor/templates/generator/scaffold/implementation/controllers/collection.rb +77 -0
- data/tasks/thor/templates/generator/scaffold/implementation/resources/base.rb +11 -0
- data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +45 -0
- data/tasks/thor/templates/generator/scaffold/models/active_record.rb +6 -0
- data/tasks/thor/templates/generator/scaffold/models/sequel.rb +6 -0
- metadata +21 -6
@@ -5,8 +5,9 @@ class DatabaseHelper
|
|
5
5
|
# This does the job for an example seeder
|
6
6
|
def self.seed!
|
7
7
|
user_data = [
|
8
|
-
{id: 11, first_name: 'Peter', last_name: 'Praxis', uuid: 'deadbeef'},
|
9
|
-
{id: 12, first_name: 'Alice', last_name: 'Trellis', uuid: 'beefdead'}
|
8
|
+
{id: 11, first_name: 'Peter', last_name: 'Praxis', uuid: 'deadbeef', email: 'peter@pan.com'},
|
9
|
+
{id: 12, first_name: 'Alice', last_name: 'Trellis', uuid: 'beefdead', email: 'alice@wonderland.com'},
|
10
|
+
{id: 13, first_name: 'Wellington', last_name: 'Lofty', uuid: 'beefbeef', email: 'well@lofty.com'},
|
10
11
|
]
|
11
12
|
(100..199).each do |i|
|
12
13
|
user_data.push id: i, first_name: "User-#{i}", last_name: "Last-#{i}", uuid: SecureRandom.hex(16).to_s
|
@@ -14,5 +15,6 @@ class DatabaseHelper
|
|
14
15
|
user_data.each_with_index do |data, i|
|
15
16
|
::User.create(**data)
|
16
17
|
end
|
18
|
+
puts "Database seeded."
|
17
19
|
end
|
18
20
|
end
|
@@ -11,10 +11,10 @@ rescue => e
|
|
11
11
|
end
|
12
12
|
|
13
13
|
# Migrate and seed the DB (only an empty in-memory DB)
|
14
|
-
|
14
|
+
|
15
15
|
ActiveRecord::Migration.verbose = false # ?? does not seem to work like this
|
16
16
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
17
|
-
|
17
|
+
require_relative '../db/seeds.rb'
|
18
18
|
|
19
19
|
RSpec.configure do |config|
|
20
20
|
config.include Rack::Test::Methods
|
@@ -13,7 +13,7 @@ describe V1::Controllers::Users do
|
|
13
13
|
|
14
14
|
context 'index' do
|
15
15
|
let(:filters_q) { '' }
|
16
|
-
let(:fields_q) { '
|
16
|
+
let(:fields_q) { 'id' }
|
17
17
|
let(:query_string) do
|
18
18
|
"filters=#{CGI.escape(filters_q)}&fields=#{CGI.escape(fields_q)}"
|
19
19
|
end
|
@@ -30,7 +30,7 @@ describe V1::Controllers::Users do
|
|
30
30
|
it 'returns only peter' do
|
31
31
|
expect(parsed_body.size).to eq(1)
|
32
32
|
# Peter has id 11 from our seeds
|
33
|
-
expect(parsed_body.map{|u| u[:
|
33
|
+
expect(parsed_body.map{|u| u[:id]}).to eq([11])
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= version_module %>
|
4
|
+
module Endpoints
|
5
|
+
class <%= plural_class %>
|
6
|
+
include Praxis::EndpointDefinition
|
7
|
+
|
8
|
+
media_type MediaTypes::<%= singular_class %>
|
9
|
+
version '<%= version %>'
|
10
|
+
|
11
|
+
description 'Praxis-generated endpoint for managing <%= plural_class %>'
|
12
|
+
|
13
|
+
<%- if action_enabled?(:index) -%>
|
14
|
+
action :index do
|
15
|
+
description 'List <%= plural_class %>'
|
16
|
+
routing { get '' }
|
17
|
+
params do
|
18
|
+
attribute :fields, Praxis::Types::FieldSelector.for(MediaTypes::<%= singular_class %>),
|
19
|
+
description: 'Fields with which to render the result.'
|
20
|
+
<%- if !pagination_enabled? -%>
|
21
|
+
=begin
|
22
|
+
# You can use pagination/ordering by enabling the PaginationPlugin, and uncommenting these lines
|
23
|
+
<%- end -%>
|
24
|
+
attribute :pagination, Praxis::Types::PaginationParams.for(MediaTypes::<%= singular_class %>)
|
25
|
+
attribute :order, Praxis::Extensions::Pagination::OrderingParams.for(MediaTypes::<%= singular_class %>)
|
26
|
+
<%- if !pagination_enabled? -%>
|
27
|
+
=end
|
28
|
+
<%- end -%>
|
29
|
+
# # Filter by attributes. Add an allowed filter per line, with the allowed operators to use
|
30
|
+
# # Also, remember to add a mapping for each in `filters_mapping` method of Resources::<%= singular_class %> class
|
31
|
+
# attribute :filters, Praxis::Types::FilteringParams.for(MediaTypes::<%= singular_class %>) do
|
32
|
+
# filter 'first_name', using: ['=', '!='], fuzzy: true
|
33
|
+
# end
|
34
|
+
end
|
35
|
+
response :ok, media_type: Praxis::Collection.of(MediaTypes::<%= singular_class %>)
|
36
|
+
end
|
37
|
+
<%- end -%>
|
38
|
+
|
39
|
+
<%- if action_enabled?(:index) -%>
|
40
|
+
action :show do
|
41
|
+
description 'Retrieve details for a specific <%= singular_class %>'
|
42
|
+
routing { get '/:id' }
|
43
|
+
params do
|
44
|
+
attribute :id, required: true
|
45
|
+
attribute :fields, Praxis::Types::FieldSelector.for(MediaTypes::<%= singular_class %>),
|
46
|
+
description: 'Fields with which to render the result.'
|
47
|
+
end
|
48
|
+
response :ok
|
49
|
+
response :not_found
|
50
|
+
end
|
51
|
+
<%- end -%>
|
52
|
+
|
53
|
+
<%- if action_enabled?(:create) -%>
|
54
|
+
action :create do
|
55
|
+
description 'Create a new <%= singular_class %>'
|
56
|
+
routing { post '' }
|
57
|
+
payload reference: MediaTypes::<%= singular_class %> do
|
58
|
+
# List the attributes you accept from the one existing in the <%= singular_class %> Mediatype
|
59
|
+
# and/or fully define any other ones you allow at creation time
|
60
|
+
# attribute :name
|
61
|
+
end
|
62
|
+
response :created
|
63
|
+
response :bad_request
|
64
|
+
end
|
65
|
+
<%- end -%>
|
66
|
+
|
67
|
+
<%- if action_enabled?(:update) -%>
|
68
|
+
action :update do
|
69
|
+
description 'Update one or more attributes of an existing <%= singular_class %>'
|
70
|
+
routing { patch '/:id' }
|
71
|
+
params do
|
72
|
+
attribute :id, required: true
|
73
|
+
end
|
74
|
+
payload reference: MediaTypes::<%= singular_class %> do
|
75
|
+
# List the attributes you accept from the one existing in the <%= singular_class %> Mediatype
|
76
|
+
# and/or fully define any other ones you allow to change
|
77
|
+
# attribute :name
|
78
|
+
end
|
79
|
+
response :no_content
|
80
|
+
response :bad_request
|
81
|
+
end
|
82
|
+
<%- end -%>
|
83
|
+
|
84
|
+
<%- if action_enabled?(:update) -%>
|
85
|
+
action :delete do
|
86
|
+
description 'Deletes a <%= singular_class %>'
|
87
|
+
routing { delete '/:id' }
|
88
|
+
params do
|
89
|
+
attribute :id, required: true
|
90
|
+
end
|
91
|
+
response :no_content
|
92
|
+
response :not_found
|
93
|
+
end
|
94
|
+
<%- end -%>
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= version_module %>
|
4
|
+
module MediaTypes
|
5
|
+
class <%= singular_class %> < Praxis::MediaType
|
6
|
+
identifier 'application/json'
|
7
|
+
|
8
|
+
domain_model '<%= version_module %>::Resources::<%= singular_class %>'
|
9
|
+
description 'Structural definition of a <%= singular_class %>'
|
10
|
+
|
11
|
+
attributes do
|
12
|
+
attribute :id, Integer, description: '<%= singular_class %> identifier'
|
13
|
+
# <INSERT MORE ATTRIBUTES HERE>
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= version_module %>
|
4
|
+
module Controllers
|
5
|
+
class <%= plural_class %>
|
6
|
+
include Praxis::Controller
|
7
|
+
|
8
|
+
implements Endpoints::<%= plural_class %>
|
9
|
+
|
10
|
+
<%- if action_enabled?(:index) -%>
|
11
|
+
# Retrieve all <%= plural_class %> with the right necessary associations
|
12
|
+
# and render them appropriately with the requested field selection
|
13
|
+
def index
|
14
|
+
objects = build_query(model_class).all
|
15
|
+
display(objects)
|
16
|
+
end
|
17
|
+
<%- end -%>
|
18
|
+
|
19
|
+
<%- if action_enabled?(:show) -%>
|
20
|
+
# Retrieve a single <%= singular_class %> with the right necessary associations
|
21
|
+
# and render them appropriately with the requested field selection
|
22
|
+
def show(id:, **_args)
|
23
|
+
model = build_query(model_class.where(id: id)).first
|
24
|
+
return Praxis::Responses::NotFound.new if model.nil?
|
25
|
+
|
26
|
+
display(model)
|
27
|
+
end
|
28
|
+
<%- end -%>
|
29
|
+
|
30
|
+
<%- if action_enabled?(:create) -%>
|
31
|
+
# Creates a new <%= singular_class %>
|
32
|
+
def create
|
33
|
+
# A good pattern is to call the same name method on the corresponding resource,
|
34
|
+
# passing the incoming payload, or massaging it first
|
35
|
+
created_resource = Resources::<%= singular_class%>.create(request.payload)
|
36
|
+
|
37
|
+
# Respond with a created if it successfully finished
|
38
|
+
Praxis::Responses::Created.new(location: created_resource.href)
|
39
|
+
end
|
40
|
+
<%- end -%>
|
41
|
+
|
42
|
+
<%- if action_enabled?(:update) -%>
|
43
|
+
# Updates some of the information of a <%= singular_class %>
|
44
|
+
def update(id:)
|
45
|
+
# A good pattern is to call the same name method on the corresponding resource,
|
46
|
+
# passing the incoming id and payload (or massaging it first)
|
47
|
+
updated_resource = Resources::<%= singular_class %>.update(
|
48
|
+
id: id,
|
49
|
+
payload: request.payload,
|
50
|
+
)
|
51
|
+
return Praxis::Responses::NotFound.new unless updated_resource
|
52
|
+
|
53
|
+
Praxis::Responses::NoContent.new
|
54
|
+
end
|
55
|
+
<%- end -%>
|
56
|
+
|
57
|
+
<%- if action_enabled?(:delete) -%>
|
58
|
+
# Deletes an existing <%= singular_class %>
|
59
|
+
def delete(id:)
|
60
|
+
# A good pattern is to call the same name method on the corresponding resource,
|
61
|
+
# maybe passing the already loaded model
|
62
|
+
deleted_resource = Resources::<%= singular_class %>.delete(
|
63
|
+
id: id
|
64
|
+
)
|
65
|
+
return Praxis::Responses::NotFound.new unless deleted_resource
|
66
|
+
|
67
|
+
Praxis::Responses::NoContent.new
|
68
|
+
end
|
69
|
+
<%- end -%>
|
70
|
+
|
71
|
+
# Use the model class as the base query but you might want to change that
|
72
|
+
def model_class
|
73
|
+
::<%= singular_class %> #Change it to the appropriate DB model class
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= version_module %>
|
4
|
+
module Resources
|
5
|
+
class Base < Praxis::Mapper::Resource
|
6
|
+
# Base for all <%= version_module %> resources.
|
7
|
+
# Resources withing a single version should have resource mappings separate from other versions
|
8
|
+
# and the Mapper::Resource will appropriately maintain different model_maps for each Base classes
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module <%= version_module %>
|
4
|
+
module Resources
|
5
|
+
class <%= singular_class %> < Base
|
6
|
+
model ::<%= singular_class %> # Change it if it maps to a different DB model class
|
7
|
+
|
8
|
+
# Define the name mapping from API filter params, to model attribute/associations
|
9
|
+
# when they aren't 1:1
|
10
|
+
# filters_mapping(
|
11
|
+
# 'name': 'name',
|
12
|
+
# 'label': 'association.label_name'
|
13
|
+
# )
|
14
|
+
|
15
|
+
# Add dependencies for resource attributes to other attributes and/or model associations
|
16
|
+
# property :href, dependencies: %i[id]
|
17
|
+
|
18
|
+
<%- if action_enabled?(:create) -%>
|
19
|
+
def self.create(payload)
|
20
|
+
# Assuming the API field names directly map the the model attributes. Massage if appropriate.
|
21
|
+
self.new(model.create(**payload.to_h))
|
22
|
+
end
|
23
|
+
<%- end -%>
|
24
|
+
|
25
|
+
<%- if action_enabled?(:update) -%>
|
26
|
+
def self.update(id:, payload:)
|
27
|
+
record = model.find_by(id: id)
|
28
|
+
return nil unless record
|
29
|
+
# Assuming the API field names directly map the the model attributes. Massage if appropriate.
|
30
|
+
record.update(**payload.to_h)
|
31
|
+
self.new(record)
|
32
|
+
end
|
33
|
+
<%- end -%>
|
34
|
+
|
35
|
+
<%- if action_enabled?(:delete) -%>
|
36
|
+
def self.delete(id:)
|
37
|
+
record = model.find_by(id: id)
|
38
|
+
return nil unless record
|
39
|
+
record.destroy
|
40
|
+
self.new(record)
|
41
|
+
end
|
42
|
+
<%- end -%>
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: praxis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.pre.
|
4
|
+
version: 2.0.pre.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep M. Blanquer
|
8
8
|
- Dane Jensen
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-04-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -367,7 +367,7 @@ dependencies:
|
|
367
367
|
- - ">"
|
368
368
|
- !ruby/object:Gem::Version
|
369
369
|
version: '4'
|
370
|
-
description:
|
370
|
+
description:
|
371
371
|
email:
|
372
372
|
- blanquer@gmail.com
|
373
373
|
- dane.jensen@gmail.com
|
@@ -446,6 +446,7 @@ files:
|
|
446
446
|
- lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb
|
447
447
|
- lib/praxis/extensions/attribute_filtering/filter_tree_node.rb
|
448
448
|
- lib/praxis/extensions/attribute_filtering/filtering_params.rb
|
449
|
+
- lib/praxis/extensions/attribute_filtering/filters_parser.rb
|
449
450
|
- lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb
|
450
451
|
- lib/praxis/extensions/field_expansion.rb
|
451
452
|
- lib/praxis/extensions/field_selection.rb
|
@@ -540,6 +541,7 @@ files:
|
|
540
541
|
- spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb
|
541
542
|
- spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb
|
542
543
|
- spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb
|
544
|
+
- spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb
|
543
545
|
- spec/praxis/extensions/field_expansion_spec.rb
|
544
546
|
- spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb
|
545
547
|
- spec/praxis/extensions/field_selection/field_selector_spec.rb
|
@@ -614,6 +616,8 @@ files:
|
|
614
616
|
- tasks/loader.thor
|
615
617
|
- tasks/thor/app.rb
|
616
618
|
- tasks/thor/example.rb
|
619
|
+
- tasks/thor/model.rb
|
620
|
+
- tasks/thor/scaffold.rb
|
617
621
|
- tasks/thor/templates/generator/empty_app/.gitignore
|
618
622
|
- tasks/thor/templates/generator/empty_app/Gemfile
|
619
623
|
- tasks/thor/templates/generator/empty_app/README.md
|
@@ -642,22 +646,33 @@ files:
|
|
642
646
|
- tasks/thor/templates/generator/example_app/Gemfile
|
643
647
|
- tasks/thor/templates/generator/example_app/Rakefile
|
644
648
|
- tasks/thor/templates/generator/example_app/app/models/user.rb
|
649
|
+
- tasks/thor/templates/generator/example_app/app/v1/concerns/controller_base.rb
|
650
|
+
- tasks/thor/templates/generator/example_app/app/v1/concerns/href.rb
|
645
651
|
- tasks/thor/templates/generator/example_app/app/v1/controllers/users.rb
|
652
|
+
- tasks/thor/templates/generator/example_app/app/v1/resources/base.rb
|
646
653
|
- tasks/thor/templates/generator/example_app/app/v1/resources/user.rb
|
647
654
|
- tasks/thor/templates/generator/example_app/config.ru
|
648
655
|
- tasks/thor/templates/generator/example_app/config/environment.rb
|
649
656
|
- tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb
|
657
|
+
- tasks/thor/templates/generator/example_app/db/seeds.rb
|
650
658
|
- tasks/thor/templates/generator/example_app/design/api.rb
|
651
659
|
- tasks/thor/templates/generator/example_app/design/v1/endpoints/users.rb
|
652
660
|
- tasks/thor/templates/generator/example_app/design/v1/media_types/user.rb
|
653
661
|
- tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb
|
654
662
|
- tasks/thor/templates/generator/example_app/spec/spec_helper.rb
|
655
663
|
- tasks/thor/templates/generator/example_app/spec/v1/controllers/users_spec.rb
|
664
|
+
- tasks/thor/templates/generator/scaffold/design/endpoints/collection.rb
|
665
|
+
- tasks/thor/templates/generator/scaffold/design/media_types/item.rb
|
666
|
+
- tasks/thor/templates/generator/scaffold/implementation/controllers/collection.rb
|
667
|
+
- tasks/thor/templates/generator/scaffold/implementation/resources/base.rb
|
668
|
+
- tasks/thor/templates/generator/scaffold/implementation/resources/item.rb
|
669
|
+
- tasks/thor/templates/generator/scaffold/models/active_record.rb
|
670
|
+
- tasks/thor/templates/generator/scaffold/models/sequel.rb
|
656
671
|
homepage: https://github.com/praxis/praxis
|
657
672
|
licenses:
|
658
673
|
- MIT
|
659
674
|
metadata: {}
|
660
|
-
post_install_message:
|
675
|
+
post_install_message:
|
661
676
|
rdoc_options: []
|
662
677
|
require_paths:
|
663
678
|
- lib
|
@@ -673,7 +688,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
673
688
|
version: 1.3.1
|
674
689
|
requirements: []
|
675
690
|
rubygems_version: 3.1.2
|
676
|
-
signing_key:
|
691
|
+
signing_key:
|
677
692
|
specification_version: 4
|
678
693
|
summary: Building APIs the way you want it.
|
679
694
|
test_files: []
|