praxis 2.0.pre.9 → 2.0.pre.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +11 -0
- data/TODO.md +1 -4
- data/bin/praxis +11 -13
- data/lib/praxis.rb +10 -3
- data/lib/praxis/action_definition.rb +15 -13
- data/lib/praxis/action_definition/headers_dsl_compiler.rb +0 -7
- data/lib/praxis/api_general_info.rb +1 -1
- data/lib/praxis/application.rb +6 -2
- data/lib/praxis/blueprint.rb +357 -0
- data/lib/praxis/bootloader.rb +9 -3
- data/lib/praxis/bootloader_stages/environment.rb +15 -13
- data/lib/praxis/collection.rb +1 -11
- data/lib/praxis/config_hash.rb +44 -0
- data/lib/praxis/docs/{openapi → open_api}/info_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/media_type_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/operation_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/parameter_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/paths_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/request_body_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/response_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/responses_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/schema_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/server_object.rb +0 -0
- data/lib/praxis/docs/{openapi → open_api}/tag_object.rb +0 -0
- data/lib/praxis/docs/open_api_generator.rb +90 -5
- data/lib/praxis/endpoint_definition.rb +273 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +1 -1
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +1 -1
- data/lib/praxis/extensions/field_expansion.rb +3 -36
- data/lib/praxis/extensions/pagination.rb +2 -2
- data/lib/praxis/extensions/pagination/ordering_params.rb +1 -1
- data/lib/praxis/extensions/pagination/pagination_params.rb +6 -4
- data/lib/praxis/field_expander.rb +90 -0
- data/lib/praxis/finalizable.rb +34 -0
- data/lib/praxis/mapper/selector_generator.rb +1 -1
- data/lib/praxis/media_type.rb +3 -68
- data/lib/praxis/plugin_concern.rb +1 -1
- data/lib/praxis/plugins/mapper_plugin.rb +7 -7
- data/lib/praxis/renderer.rb +88 -0
- data/lib/praxis/request.rb +1 -1
- data/lib/praxis/resource_definition.rb +2 -311
- data/lib/praxis/response_definition.rb +2 -10
- data/lib/praxis/response_template.rb +3 -3
- data/lib/praxis/router.rb +2 -2
- data/lib/praxis/routing_config.rb +1 -1
- data/lib/praxis/tasks/api_docs.rb +13 -63
- data/lib/praxis/tasks/routes.rb +1 -1
- data/lib/praxis/types/media_type_common.rb +1 -11
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +0 -1
- data/spec/functional_spec.rb +5 -9
- data/spec/praxis/action_definition_spec.rb +12 -20
- data/spec/praxis/blueprint_spec.rb +373 -0
- data/spec/praxis/bootloader_spec.rb +10 -2
- data/spec/praxis/collection_spec.rb +0 -13
- data/spec/praxis/config_hash_spec.rb +64 -0
- data/spec/praxis/{resource_definition_spec.rb → endpoint_definition_spec.rb} +37 -64
- data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +4 -6
- data/spec/praxis/extensions/field_expansion_spec.rb +5 -24
- data/spec/praxis/field_expander_spec.rb +149 -0
- data/spec/praxis/media_type_identifier_spec.rb +5 -4
- data/spec/praxis/media_type_spec.rb +4 -93
- data/spec/praxis/renderer_spec.rb +188 -0
- data/spec/praxis/response_definition_spec.rb +0 -31
- data/spec/praxis/response_spec.rb +1 -1
- data/spec/praxis/router_spec.rb +8 -8
- data/spec/praxis/routing_config_spec.rb +3 -3
- data/spec/spec_app/app/controllers/instances.rb +13 -7
- data/spec/spec_app/design/media_types/instance.rb +1 -19
- data/spec/spec_app/design/media_types/volume.rb +1 -1
- data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -14
- data/spec/spec_app/design/resources/instances.rb +5 -8
- data/spec/spec_app/design/resources/volume_snapshots.rb +1 -1
- data/spec/spec_app/design/resources/volumes.rb +1 -1
- data/spec/support/spec_authorization_plugin.rb +1 -1
- data/spec/support/spec_blueprints.rb +72 -0
- data/spec/support/{spec_resource_definitions.rb → spec_endpoint_definitions.rb} +2 -2
- data/spec/support/spec_media_types.rb +6 -26
- data/tasks/thor/app.rb +8 -34
- data/tasks/thor/example.rb +45 -285
- data/tasks/thor/templates/generator/empty_app/.gitignore +0 -1
- data/tasks/thor/templates/generator/empty_app/Gemfile +7 -23
- data/tasks/thor/templates/generator/empty_app/README.md +1 -1
- data/tasks/thor/templates/generator/empty_app/Rakefile +4 -13
- data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/config/environment.rb +25 -17
- data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/docs/.empty_directory +0 -0
- data/tasks/thor/templates/generator/empty_app/docs/.gitkeep +0 -0
- data/tasks/thor/templates/generator/empty_app/spec/spec_helper.rb +14 -9
- data/tasks/thor/templates/generator/example_app/.gitignore +1 -0
- data/tasks/thor/templates/generator/example_app/Gemfile +19 -0
- data/tasks/thor/templates/generator/example_app/Rakefile +54 -0
- data/tasks/thor/templates/generator/example_app/app/models/user.rb +6 -0
- data/tasks/thor/templates/generator/example_app/app/v1/controllers/users.rb +17 -0
- data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +46 -0
- data/tasks/thor/templates/generator/example_app/config.ru +31 -0
- data/tasks/thor/templates/generator/example_app/config/environment.rb +40 -0
- data/tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb +11 -0
- data/tasks/thor/templates/generator/example_app/design/api.rb +18 -0
- data/tasks/thor/templates/generator/example_app/design/v1/endpoints/users.rb +37 -0
- data/tasks/thor/templates/generator/example_app/design/v1/media_types/user.rb +26 -0
- data/tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb +18 -0
- data/tasks/thor/templates/generator/example_app/spec/spec_helper.rb +42 -0
- data/tasks/thor/templates/generator/example_app/spec/v1/controllers/users_spec.rb +37 -0
- metadata +49 -135
- data/lib/api_browser/.bowerrc +0 -3
- data/lib/api_browser/.editorconfig +0 -21
- data/lib/api_browser/Gruntfile.js +0 -581
- data/lib/api_browser/app/index.html +0 -59
- data/lib/api_browser/app/js/app.js +0 -48
- data/lib/api_browser/app/js/controllers/action.js +0 -47
- data/lib/api_browser/app/js/controllers/controller.js +0 -10
- data/lib/api_browser/app/js/controllers/menu.js +0 -93
- data/lib/api_browser/app/js/controllers/trait.js +0 -10
- data/lib/api_browser/app/js/controllers/type.js +0 -24
- data/lib/api_browser/app/js/directives/attribute_description.js +0 -56
- data/lib/api_browser/app/js/directives/attribute_table.js +0 -28
- data/lib/api_browser/app/js/directives/conditional_requirements.js +0 -13
- data/lib/api_browser/app/js/directives/fixed_if_fits.js +0 -38
- data/lib/api_browser/app/js/directives/highlight.js +0 -14
- data/lib/api_browser/app/js/directives/menu_item.js +0 -59
- data/lib/api_browser/app/js/directives/no_container.js +0 -8
- data/lib/api_browser/app/js/directives/readable_list.js +0 -87
- data/lib/api_browser/app/js/directives/request_examples.js +0 -31
- data/lib/api_browser/app/js/directives/type_placeholder.js +0 -30
- data/lib/api_browser/app/js/directives/url.js +0 -15
- data/lib/api_browser/app/js/factories/Configuration.js +0 -12
- data/lib/api_browser/app/js/factories/Documentation.js +0 -61
- data/lib/api_browser/app/js/factories/Example.js +0 -51
- data/lib/api_browser/app/js/factories/PageInfo.js +0 -9
- data/lib/api_browser/app/js/factories/normalize_attributes.js +0 -20
- data/lib/api_browser/app/js/factories/prepare_template.js +0 -15
- data/lib/api_browser/app/js/factories/template_for.js +0 -128
- data/lib/api_browser/app/js/filters/attribute_name.js +0 -10
- data/lib/api_browser/app/js/filters/friendly_json.js +0 -5
- data/lib/api_browser/app/js/filters/has_requirement.js +0 -14
- data/lib/api_browser/app/js/filters/header_info.js +0 -9
- data/lib/api_browser/app/js/filters/is_empty.js +0 -8
- data/lib/api_browser/app/js/filters/markdown.js +0 -6
- data/lib/api_browser/app/js/filters/resource_name.js +0 -5
- data/lib/api_browser/app/js/filters/tag_requirement.js +0 -13
- data/lib/api_browser/app/sass/modules/_body.scss +0 -40
- data/lib/api_browser/app/sass/modules/_cloke.scss +0 -8
- data/lib/api_browser/app/sass/modules/_header.scss +0 -10
- data/lib/api_browser/app/sass/modules/_nav.scss +0 -7
- data/lib/api_browser/app/sass/modules/_sidebar.scss +0 -134
- data/lib/api_browser/app/sass/modules/_switch.scss +0 -55
- data/lib/api_browser/app/sass/modules/_table.scss +0 -13
- data/lib/api_browser/app/sass/praxis.scss +0 -70
- data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +0 -774
- data/lib/api_browser/app/views/action.html +0 -97
- data/lib/api_browser/app/views/builtin/field-selector.html +0 -24
- data/lib/api_browser/app/views/controller.html +0 -55
- data/lib/api_browser/app/views/directives/attribute_description.html +0 -2
- data/lib/api_browser/app/views/directives/attribute_description/default.html +0 -2
- data/lib/api_browser/app/views/directives/attribute_description/example.html +0 -13
- data/lib/api_browser/app/views/directives/attribute_description/headers.html +0 -8
- data/lib/api_browser/app/views/directives/attribute_description/member_options.html +0 -4
- data/lib/api_browser/app/views/directives/attribute_description/values.html +0 -14
- data/lib/api_browser/app/views/directives/attribute_table.html +0 -17
- data/lib/api_browser/app/views/directives/menu_item.html +0 -8
- data/lib/api_browser/app/views/directives/url.html +0 -3
- data/lib/api_browser/app/views/examples/general.html +0 -26
- data/lib/api_browser/app/views/home.html +0 -5
- data/lib/api_browser/app/views/layout.html +0 -8
- data/lib/api_browser/app/views/menu.html +0 -42
- data/lib/api_browser/app/views/navbar.html +0 -9
- data/lib/api_browser/app/views/trait.html +0 -13
- data/lib/api_browser/app/views/type.html +0 -6
- data/lib/api_browser/app/views/type/details.html +0 -33
- data/lib/api_browser/app/views/types/embedded/array.html +0 -2
- data/lib/api_browser/app/views/types/embedded/default.html +0 -12
- data/lib/api_browser/app/views/types/embedded/field-selector.html +0 -13
- data/lib/api_browser/app/views/types/embedded/links.html +0 -11
- data/lib/api_browser/app/views/types/embedded/requirements.html +0 -6
- data/lib/api_browser/app/views/types/embedded/single_req.html +0 -9
- data/lib/api_browser/app/views/types/embedded/struct.html +0 -14
- data/lib/api_browser/app/views/types/label/link.html +0 -1
- data/lib/api_browser/app/views/types/label/primitive.html +0 -1
- data/lib/api_browser/app/views/types/label/primitive_collection.html +0 -1
- data/lib/api_browser/app/views/types/label/type.html +0 -1
- data/lib/api_browser/app/views/types/label/type_collection.html +0 -1
- data/lib/api_browser/app/views/types/main/array.html +0 -22
- data/lib/api_browser/app/views/types/main/default.html +0 -23
- data/lib/api_browser/app/views/types/main/hash.html +0 -23
- data/lib/api_browser/app/views/types/standalone/array.html +0 -3
- data/lib/api_browser/app/views/types/standalone/default.html +0 -18
- data/lib/api_browser/app/views/types/standalone/struct.html +0 -2
- data/lib/api_browser/bower_template.json +0 -41
- data/lib/api_browser/package-lock.json +0 -7110
- data/lib/api_browser/package.json +0 -43
- data/lib/praxis/docs/generator.rb +0 -243
- data/lib/praxis/docs/link_builder.rb +0 -30
- data/lib/praxis/links.rb +0 -135
- data/lib/praxis/types/multipart.rb +0 -109
- data/spec/api_browser/directives/type_placeholder_spec.js +0 -134
- data/spec/api_browser/factories/configuration_spec.js +0 -32
- data/spec/api_browser/factories/documentation_spec.js +0 -100
- data/spec/api_browser/factories/normalize_attributes_spec.js +0 -92
- data/spec/api_browser/factories/template_for_spec.js +0 -67
- data/spec/api_browser/filters/attribute_name_spec.js +0 -23
- data/spec/praxis/types/multipart_spec.rb +0 -112
- data/tasks/thor/templates/generator/empty_app/.rspec +0 -1
- data/tasks/thor/templates/generator/empty_app/Guardfile +0 -3
- data/tasks/thor/templates/generator/empty_app/config/rainbows.rb +0 -57
- data/tasks/thor/templates/generator/empty_app/docs/app.js +0 -1
- data/tasks/thor/templates/generator/empty_app/docs/styles.scss +0 -3
@@ -1,29 +1,13 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gem 'praxis'
|
4
|
-
gem '
|
5
|
-
gem 'praxis-blueprints', github: 'praxis/praxis-blueprints'
|
6
|
-
|
7
|
-
gem 'rainbows', require: false
|
8
|
-
gem 'rake'
|
9
|
-
gem 'pry'
|
10
|
-
gem 'pry-byebug'
|
3
|
+
gem 'praxis'
|
4
|
+
gem 'rack'
|
11
5
|
|
12
6
|
group :development, :test do
|
13
|
-
gem
|
7
|
+
gem 'rack-test'
|
14
8
|
gem "rspec" # needed for rake task
|
15
|
-
gem 'rspec-its'
|
16
|
-
gem 'rspec-collection_matchers'
|
17
|
-
|
18
|
-
gem 'foreman', :require => false
|
19
|
-
|
20
|
-
platform :mri_19, :mri_20 do
|
21
|
-
gem 'shotgun', :require => false
|
22
|
-
gem "guard"
|
23
|
-
gem "guard-rspec"
|
24
|
-
end
|
25
|
-
end
|
26
9
|
|
27
|
-
|
28
|
-
gem '
|
29
|
-
|
10
|
+
gem 'rake'
|
11
|
+
gem 'pry'
|
12
|
+
gem 'pry-byebug'
|
13
|
+
end
|
@@ -5,21 +5,12 @@ Bundler.require(:default, ENV['RACK_ENV'])
|
|
5
5
|
|
6
6
|
require 'praxis/tasks'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
# load up the Praxis app
|
11
|
-
task :environment do
|
12
|
-
Praxis::Application.instance.setup
|
13
|
-
end
|
14
|
-
|
15
|
-
desc "console"
|
16
|
-
task :console => :environment do
|
17
|
-
require 'pry'
|
18
|
-
require 'pry-byebug'
|
19
|
-
pry
|
20
|
-
end
|
8
|
+
desc "Drop into a console with the full application loaded"
|
9
|
+
task console: 'praxis:console'
|
21
10
|
|
22
11
|
require 'rspec/core/rake_task'
|
23
12
|
RSpec::Core::RakeTask.new(:spec)
|
24
13
|
|
25
14
|
Dir["lib/tasks/**/*.rake"].each { |ext| load ext }
|
15
|
+
|
16
|
+
task :default => :spec
|
File without changes
|
File without changes
|
@@ -1,17 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
1
|
+
|
2
|
+
Praxis::Application.configure do |application|
|
3
|
+
# This is a commented out copy of the default Praxis layout
|
4
|
+
# This example app follows the standard practices, so there is no reason to override it
|
5
|
+
# If we wanted to organize the structure and ordering of files, we can uncomment the layout
|
6
|
+
# and define it at our own leisure
|
7
|
+
# application.layout do
|
8
|
+
# map :initializers, 'config/initializers/**/*'
|
9
|
+
# map :lib, 'lib/**/*'
|
10
|
+
# map :design, 'design/' do
|
11
|
+
# map :api, 'api.rb'
|
12
|
+
# map :helpers, '**/helpers/**/*'
|
13
|
+
# map :types, '**/types/**/*'
|
14
|
+
# map :media_types, '**/media_types/**/*'
|
15
|
+
# map :endpoints, '**/endpoints/**/*'
|
16
|
+
# end
|
17
|
+
# map :app, 'app/' do
|
18
|
+
# map :models, 'models/**/*'
|
19
|
+
# map :responses, '**/responses/**/*'
|
20
|
+
# map :exceptions, '**/exceptions/**/*'
|
21
|
+
# map :resources, '**/resources/**/*'
|
22
|
+
# map :controllers, '**/controllers/**/*'
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
end
|
File without changes
|
data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.gitkeep
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -4,15 +4,20 @@ Bundler.require :default, :test
|
|
4
4
|
RSpec.configure do |config|
|
5
5
|
config.include Rack::Test::Methods
|
6
6
|
|
7
|
-
config.before(:suite) do
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
# config.before(:suite) do
|
8
|
+
# Praxis::Blueprint.caching_enabled = true
|
9
|
+
# end
|
11
10
|
|
12
|
-
config.before(:each) do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
11
|
+
# config.before(:each) do
|
12
|
+
# Praxis::Blueprint.cache = Hash.new do |hash, key|
|
13
|
+
# hash[key] = Hash.new
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
end
|
17
17
|
|
18
|
+
def app
|
19
|
+
Rack::Builder.parse_file(File.expand_path('../config.ru', __dir__)).first
|
20
|
+
rescue => e
|
21
|
+
puts "Application failed to initialize: #{e}"
|
22
|
+
exit 1
|
18
23
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
development.sqlite3
|
@@ -0,0 +1,19 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'praxis'
|
4
|
+
gem 'rack'
|
5
|
+
gem 'sqlite3'
|
6
|
+
gem 'activerecord'
|
7
|
+
gem 'puma' # A much better web server than the default webrick
|
8
|
+
gem 'parslet' # For field selection extension
|
9
|
+
gem 'link_header' # For pagination extensions
|
10
|
+
|
11
|
+
group :development, :test do
|
12
|
+
gem 'rake'
|
13
|
+
gem 'rack-test'
|
14
|
+
gem "rspec" # needed for rake task
|
15
|
+
gem 'database_cleaner' # For transactional DB tests
|
16
|
+
|
17
|
+
gem 'pry'
|
18
|
+
gem 'pry-byebug'
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
ENV['RACK_ENV'] = 'development'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
RSpec::Core::RakeTask.new(:spec)
|
4
|
+
|
5
|
+
require 'praxis'
|
6
|
+
require 'praxis/tasks'
|
7
|
+
|
8
|
+
# Setup Activerecord migrations
|
9
|
+
require 'active_record'
|
10
|
+
db_dir = File.expand_path('../db', __dir__)
|
11
|
+
ActiveRecord::Tasks::DatabaseTasks.env = ENV['RACK_ENV']
|
12
|
+
ActiveRecord::Tasks::DatabaseTasks.db_dir = db_dir
|
13
|
+
ActiveRecord::Tasks::DatabaseTasks.migrations_paths = File.join(db_dir, 'migrate')
|
14
|
+
|
15
|
+
# Redefine the environment task to load our app
|
16
|
+
Rake::Task['praxis:environment'].clear
|
17
|
+
namespace :praxis do
|
18
|
+
task :environment do
|
19
|
+
FULL_APP = Rack::Builder.parse_file(File.expand_path('./config.ru', __dir__)).first
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Dir['lib/tasks/**/*.rake'].each { |ext| load ext }
|
24
|
+
|
25
|
+
# Inlined basic DB tasks to avoid packaging more files and directories
|
26
|
+
namespace :db do
|
27
|
+
require 'active_record/tasks/database_tasks'
|
28
|
+
|
29
|
+
desc 'migrate'
|
30
|
+
task migrate: 'praxis:environment' do
|
31
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate
|
32
|
+
puts "Database migrated."
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'seed with example data'
|
36
|
+
task seed: 'praxis:environment' do
|
37
|
+
require_relative 'spec/helpers/database_helper'
|
38
|
+
DatabaseHelper.seed!
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'drops current database'
|
42
|
+
task drop: 'praxis:environment' do
|
43
|
+
db_file = "development.sqlite3"
|
44
|
+
puts "Removing file #{db_file}"
|
45
|
+
`rm -f #{db_file}`
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'creates configured database'
|
49
|
+
task create: 'praxis:environment' do
|
50
|
+
puts "Creating file development.sqlite3"
|
51
|
+
ActiveRecord::Base.connection.execute("SELECT 1")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module V1
|
4
|
+
module Controllers
|
5
|
+
class Users
|
6
|
+
include Praxis::Controller
|
7
|
+
include Praxis::Extensions::Rendering
|
8
|
+
|
9
|
+
implements V1::Endpoints::Users
|
10
|
+
|
11
|
+
def index
|
12
|
+
objects = build_query(::User)
|
13
|
+
display(objects)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module V1
|
4
|
+
module Resources
|
5
|
+
class User < Praxis::Mapper::Resource
|
6
|
+
model ::User
|
7
|
+
|
8
|
+
# Mappings for the allowed filterd
|
9
|
+
filters_mapping(
|
10
|
+
'email': 'email',
|
11
|
+
'first_name': 'first_name',
|
12
|
+
# Complex (convoluted?) mapping of state, just to show how we can modify and adapt the values/fields/operators
|
13
|
+
'state': lambda do |spec|
|
14
|
+
case spec[:value].to_s
|
15
|
+
when 'pending' # Pending users do not have a uuid
|
16
|
+
{ name: :uuid, value: nil, op: spec[:op] }
|
17
|
+
when 'active' # Active users do not have a uuid (so "flip" the original equality condition)
|
18
|
+
opposite_op = spec[:op] == '=' ? '!=' : '='
|
19
|
+
{ name: :uuid, value: nil, op: opposite_op }
|
20
|
+
else
|
21
|
+
raise "Cannot filter users by state #{spec[:value]}"
|
22
|
+
end
|
23
|
+
end,
|
24
|
+
)
|
25
|
+
|
26
|
+
# Example of a property that depends on a differently named DB field
|
27
|
+
property :uid, dependencies: %i[id]
|
28
|
+
# To compute the full_name (method below) we need to load first and last names from the DB
|
29
|
+
property :full_name, dependencies: %i[first_name last_name]
|
30
|
+
|
31
|
+
def uid
|
32
|
+
id # underlying id field of the model
|
33
|
+
end
|
34
|
+
|
35
|
+
# Computed attribute: if uuid nil, user in in a pending stat, else active
|
36
|
+
def state
|
37
|
+
self.uuid.nil? ? 'pending' : 'active'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Computed attribute the combines first and last
|
41
|
+
def full_name
|
42
|
+
[first_name, last_name].join(' ')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -p 8888
|
2
|
+
|
3
|
+
ENV['RACK_ENV'] ||= 'development'
|
4
|
+
Bundler.setup(:default, ENV['RACK_ENV'])
|
5
|
+
Bundler.require(:default, ENV['RACK_ENV'])
|
6
|
+
|
7
|
+
# Want to take advantage of some of the Praxis' extensions for:
|
8
|
+
# API field selection (a la GraphQL) - for querying and rendering
|
9
|
+
# API filtering extensions (to add "where clauses") in listings
|
10
|
+
# Views and partial rendering (for ActiveRecord models)
|
11
|
+
|
12
|
+
require 'praxis/plugins/mapper_plugin'
|
13
|
+
require 'praxis/mapper/active_model_compat'
|
14
|
+
require 'praxis/extensions/field_selection'
|
15
|
+
require 'praxis/plugins/pagination_plugin'
|
16
|
+
|
17
|
+
# Start the sqlite DB
|
18
|
+
case ENV['RACK_ENV']
|
19
|
+
when 'test'
|
20
|
+
ActiveRecord::Base.establish_connection(
|
21
|
+
adapter: 'sqlite3',
|
22
|
+
database: ':memory:'
|
23
|
+
)
|
24
|
+
else
|
25
|
+
ActiveRecord::Base.establish_connection(
|
26
|
+
adapter: 'sqlite3',
|
27
|
+
database: "development.sqlite3"
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
run Praxis::Application.instance.setup
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
Praxis::Application.configure do |application|
|
3
|
+
|
4
|
+
# Configure the Mapper plugin (if we want to use all the filtering/field_selection extensions)
|
5
|
+
application.bootloader.use Praxis::Plugins::MapperPlugin
|
6
|
+
# Cconfigure the Pagination plugin (if we want to use all the pagination/ordering extensions)
|
7
|
+
application.bootloader.use Praxis::Plugins::PaginationPlugin, {
|
8
|
+
# max_items: 500, # Unlimited by default,
|
9
|
+
# default_page_size: 100,
|
10
|
+
# paging_default_mode: {by: :id},
|
11
|
+
# disallow_paging_by_default: false,
|
12
|
+
# disallow_cursor_by_default: false,
|
13
|
+
# sorting: {
|
14
|
+
# enforce_all_fields: true
|
15
|
+
# }
|
16
|
+
}
|
17
|
+
|
18
|
+
# This is a commented out copy of the default Praxis layout
|
19
|
+
# This example app follows the standard practices, so there is no reason to override it
|
20
|
+
# If we wanted to organize the structure and ordering of files, we can uncomment the layout
|
21
|
+
# and define it at our own leisure
|
22
|
+
# application.layout do
|
23
|
+
# map :initializers, 'config/initializers/**/*'
|
24
|
+
# map :lib, 'lib/**/*'
|
25
|
+
# map :design, 'design/' do
|
26
|
+
# map :api, 'api.rb'
|
27
|
+
# map :helpers, '**/helpers/**/*'
|
28
|
+
# map :types, '**/types/**/*'
|
29
|
+
# map :media_types, '**/media_types/**/*'
|
30
|
+
# map :endpoints, '**/endpoints/**/*'
|
31
|
+
# end
|
32
|
+
# map :app, 'app/' do
|
33
|
+
# map :models, 'models/**/*'
|
34
|
+
# map :responses, '**/responses/**/*'
|
35
|
+
# map :exceptions, '**/exceptions/**/*'
|
36
|
+
# map :resources, '**/resources/**/*'
|
37
|
+
# map :controllers, '**/controllers/**/*'
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Use this file to define your overall api behavior, response templates and traits.
|
2
|
+
Praxis::ApiDefinition.define do
|
3
|
+
info do
|
4
|
+
name 'example'
|
5
|
+
title 'Example API'
|
6
|
+
|
7
|
+
# Attributes for OpenAPI docs
|
8
|
+
termsOfService 'https://mysitehere.com'
|
9
|
+
contact name: 'API Info', email: 'info@mysitehere.com'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Trait that when included will require a Bearer authorization header to be passed in.
|
13
|
+
trait :authorized do
|
14
|
+
headers do
|
15
|
+
key "Authorization", String, regexp: /^.*Bearer\s/, required: true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module V1
|
4
|
+
module Endpoints
|
5
|
+
class Users
|
6
|
+
include Praxis::EndpointDefinition
|
7
|
+
# include AuthenticatedEndpoint
|
8
|
+
|
9
|
+
media_type MediaTypes::User
|
10
|
+
version '1'
|
11
|
+
|
12
|
+
description 'Endpoints that allow the listing and manipulation of users'
|
13
|
+
|
14
|
+
action :index do
|
15
|
+
description 'List users'
|
16
|
+
routing { get '' }
|
17
|
+
params do
|
18
|
+
attribute :fields, Praxis::Types::FieldSelector.for(MediaTypes::User),
|
19
|
+
description: 'Fields with which to render the result.'
|
20
|
+
attribute :filters, Praxis::Types::FilteringParams.for(MediaTypes::User) do
|
21
|
+
filter 'state', using: ['=', '!=']
|
22
|
+
filter 'first_name', using: ['=', '!='], fuzzy: true
|
23
|
+
filter 'last_name', using: ['=', '!='], fuzzy: true
|
24
|
+
end
|
25
|
+
attribute :pagination, Praxis::Types::PaginationParams.for(MediaTypes::User) do
|
26
|
+
by_fields :uid, :first_name, :last_name
|
27
|
+
end
|
28
|
+
attribute :order, Praxis::Extensions::Pagination::OrderingParams.for(MediaTypes::User) do
|
29
|
+
by_fields :uid, :last_name, :first_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
response :ok, media_type: Praxis::Collection.of(MediaTypes::User)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|