praxis 2.0.pre.8 → 2.0.pre.13
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/.gitignore +2 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -3
- data/CHANGELOG.md +33 -0
- data/TODO.md +1 -4
- data/bin/praxis +67 -12
- 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 +16 -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 +18 -10
- 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 +91 -6
- data/lib/praxis/endpoint_definition.rb +273 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +182 -58
- data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +3 -2
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +47 -56
- data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +153 -0
- data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +20 -8
- data/lib/praxis/extensions/field_expansion.rb +3 -36
- data/lib/praxis/extensions/pagination.rb +5 -32
- 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/active_model_compat.rb +4 -0
- data/lib/praxis/mapper/resource.rb +18 -2
- data/lib/praxis/mapper/selector_generator.rb +2 -1
- data/lib/praxis/mapper/sequel_compat.rb +7 -0
- data/lib/praxis/media_type.rb +3 -68
- data/lib/praxis/plugin_concern.rb +1 -1
- data/lib/praxis/plugins/mapper_plugin.rb +24 -15
- data/lib/praxis/plugins/pagination_plugin.rb +34 -4
- 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 +17 -64
- 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 +249 -168
- data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +25 -6
- data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +190 -8
- data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +140 -0
- data/spec/praxis/extensions/field_expansion_spec.rb +5 -24
- 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/field_expander_spec.rb +149 -0
- data/spec/praxis/mapper/selector_generator_spec.rb +1 -1
- 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 +51 -285
- data/tasks/thor/model.rb +40 -0
- data/tasks/thor/scaffold.rb +117 -0
- 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 +26 -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 +61 -0
- data/tasks/thor/templates/generator/example_app/app/models/user.rb +6 -0
- data/tasks/thor/templates/generator/example_app/app/v1/concerns/controller_base.rb +24 -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/base.rb +11 -0
- data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +25 -0
- data/tasks/thor/templates/generator/example_app/config.ru +30 -0
- data/tasks/thor/templates/generator/example_app/config/environment.rb +41 -0
- data/tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb +12 -0
- data/tasks/thor/templates/generator/example_app/db/seeds.rb +6 -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 +21 -0
- data/tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb +20 -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
- 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 +64 -136
- 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
data/tasks/thor/app.rb
CHANGED
|
@@ -13,41 +13,15 @@ module PraxisGen
|
|
|
13
13
|
# Generator for a blank new app (with a full skeleton ready to get you going)
|
|
14
14
|
def new
|
|
15
15
|
puts "Creating new blank Praxis app under #{app_name}"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
def create_root_files
|
|
26
|
-
['config.ru','Gemfile','Guardfile','Rakefile','README.md'].each do |file|
|
|
27
|
-
copy_file file, "#{app_name}/#{file}"
|
|
16
|
+
# Copy example files
|
|
17
|
+
['config.ru','Gemfile','Rakefile','README.md'].each do |file|
|
|
18
|
+
copy_file file, verbose: true
|
|
19
|
+
end
|
|
20
|
+
# Copy example directories
|
|
21
|
+
root_dirs = ['config','app','design','spec','docs']
|
|
22
|
+
root_dirs.each do |dir|
|
|
23
|
+
directory dir, recursive: true
|
|
28
24
|
end
|
|
29
25
|
end
|
|
30
|
-
|
|
31
|
-
def create_config
|
|
32
|
-
copy_file "config/environment.rb", "#{app_name}/config/environment.rb"
|
|
33
|
-
copy_file "config/rainbows.rb", "#{app_name}/config/rainbows.rb"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def create_app
|
|
37
|
-
directory "app", "#{app_name}/app", :recursive => true
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def create_design
|
|
41
|
-
directory "design", "#{app_name}/design", :recursive => true
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def create_spec
|
|
45
|
-
directory "spec", "#{app_name}/spec", :recursive => true
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def create_docs
|
|
49
|
-
directory "docs", "#{app_name}/docs", :recursive => true
|
|
50
|
-
end
|
|
51
|
-
|
|
52
26
|
end
|
|
53
27
|
end
|
data/tasks/thor/example.rb
CHANGED
|
@@ -1,291 +1,57 @@
|
|
|
1
1
|
|
|
2
2
|
module PraxisGen
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# app_dir_pathname #=> 'mytest_praxisapp'
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
def app_dir_pathname
|
|
58
|
-
@app_dir_pathname ||= Pathname.new(app_name)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# Returns path string built from the set of the given strings
|
|
63
|
-
#
|
|
64
|
-
# @param [String,Array] strings
|
|
65
|
-
#
|
|
66
|
-
# @return [String]
|
|
67
|
-
#
|
|
68
|
-
# @example
|
|
69
|
-
# path('a', 'b', 'c') #=> 'my_test_app/a/b/c'
|
|
70
|
-
#
|
|
71
|
-
def path(*strings)
|
|
72
|
-
app_dir_pathname.join(*strings).to_s
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# Creates './config/environment.rb' file
|
|
77
|
-
#
|
|
78
|
-
# @return [void]
|
|
79
|
-
#
|
|
80
|
-
def generate_config_environment_rb
|
|
81
|
-
create_file path('config/environment.rb') do
|
|
82
|
-
<<-RUBY
|
|
83
|
-
# Main entry point - DO NOT MODIFY THIS FILE
|
|
84
|
-
ENV['RACK_ENV'] ||= 'development'
|
|
85
|
-
|
|
86
|
-
Bundler.require(:default, ENV['RACK_ENV'])
|
|
87
|
-
|
|
88
|
-
# Default application layout.
|
|
89
|
-
# NOTE: This layout need NOT be specified explicitly.
|
|
90
|
-
# It is provided just for illustration.
|
|
91
|
-
Praxis::Application.instance.layout do
|
|
92
|
-
map :initializers, 'config/initializers/**/*'
|
|
93
|
-
map :lib, 'lib/**/*'
|
|
94
|
-
map :design, 'design/' do
|
|
95
|
-
map :api, 'api.rb'
|
|
96
|
-
map :media_types, '**/media_types/**/*'
|
|
97
|
-
map :resources, '**/resources/**/*'
|
|
98
|
-
end
|
|
99
|
-
map :app, 'app/' do
|
|
100
|
-
map :models, 'models/**/*'
|
|
101
|
-
map :controllers, '**/controllers/**/*'
|
|
102
|
-
map :responses, '**/responses/**/*'
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
RUBY
|
|
106
|
-
end
|
|
107
|
-
nil
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# Creates './Gemfile' file
|
|
112
|
-
#
|
|
113
|
-
# @return [void]
|
|
114
|
-
#
|
|
115
|
-
def generate_gemfile
|
|
116
|
-
create_file path('Gemfile') do
|
|
117
|
-
<<-RUBY
|
|
118
|
-
source 'https://rubygems.org'
|
|
119
|
-
|
|
120
|
-
gem 'praxis'
|
|
121
|
-
gem 'rack', '~> 1.0'
|
|
122
|
-
gem 'rake'
|
|
123
|
-
|
|
124
|
-
group :development, :test do
|
|
125
|
-
gem 'rspec'
|
|
126
|
-
end
|
|
127
|
-
RUBY
|
|
128
|
-
end
|
|
129
|
-
nil
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# Creates './Rakefile' file
|
|
134
|
-
#
|
|
135
|
-
# @return [void]
|
|
136
|
-
#
|
|
137
|
-
def generate_rakefile
|
|
138
|
-
create_file path('Rakefile') do
|
|
139
|
-
<<-RUBY
|
|
140
|
-
require 'praxis'
|
|
141
|
-
require 'praxis/tasks'
|
|
142
|
-
RUBY
|
|
143
|
-
end
|
|
144
|
-
nil
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
# Creates './config.ru' file
|
|
149
|
-
#
|
|
150
|
-
# @return [void]
|
|
151
|
-
#
|
|
152
|
-
def generate_config_ru
|
|
153
|
-
create_file path('config.ru') do
|
|
154
|
-
<<-RUBY
|
|
155
|
-
#\\ -p 8888
|
|
156
|
-
|
|
157
|
-
require 'bundler/setup'
|
|
158
|
-
require 'praxis'
|
|
159
|
-
|
|
160
|
-
application = Praxis::Application.instance
|
|
161
|
-
application.logger = Logger.new(STDOUT)
|
|
162
|
-
application.setup
|
|
163
|
-
|
|
164
|
-
run application
|
|
165
|
-
RUBY
|
|
166
|
-
end
|
|
3
|
+
class Example < Thor
|
|
4
|
+
include Thor::Actions
|
|
5
|
+
|
|
6
|
+
namespace "praxis:example"
|
|
7
|
+
|
|
8
|
+
def self.source_root
|
|
9
|
+
File.dirname(__FILE__) + "/templates/generator/example_app"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
argument :app_name, required: true
|
|
13
|
+
desc "example", "Generates a new example application under an <app_name> directory to showcase some features"
|
|
14
|
+
|
|
15
|
+
def example
|
|
16
|
+
sanitized = app_name.downcase.gsub(/[^a-z0-9_\-.]/, '')
|
|
17
|
+
puts "APP_NAME: #{app_name}"
|
|
18
|
+
raise "Please use only letters, numbers, underscores, dashes or periods for the app name" unless sanitized == app_name
|
|
19
|
+
|
|
20
|
+
# Copy example files
|
|
21
|
+
root_files = ['Gemfile','config.ru','Rakefile']
|
|
22
|
+
root_files.each do |file|
|
|
23
|
+
copy_file file, verbose: true
|
|
24
|
+
end
|
|
25
|
+
# Copy example directories
|
|
26
|
+
root_dirs = ['app','config','design','db','spec']
|
|
27
|
+
root_dirs.each do |dir|
|
|
28
|
+
directory dir, recursive: true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
puts
|
|
32
|
+
puts "To run the example application:"
|
|
33
|
+
puts
|
|
34
|
+
puts " cd #{app_name}"
|
|
35
|
+
puts " bundle"
|
|
36
|
+
puts " bundle exec rake db:recreate # To create/migrate/seed the dev DB"
|
|
37
|
+
puts " bundle exec rackup # To start the web server"
|
|
38
|
+
puts
|
|
39
|
+
puts "From another terminal/app, use curl (or your favorite HTTP client) to retrieve data from the API"
|
|
40
|
+
puts " For example: "
|
|
41
|
+
puts " Get all users without filters or limit, and display only id, and first_name fields"
|
|
42
|
+
puts " curl -G -H 'X-Api-Version: 1' http://localhost:9292/users \\"
|
|
43
|
+
puts " --data-urlencode \"fields=id,first_name\""
|
|
44
|
+
puts
|
|
45
|
+
puts " Get the last 5 users, with last_names starting with \"L\" ordered by first_name (descending)"
|
|
46
|
+
puts " and display only id, first_name, last_name, and email fields"
|
|
47
|
+
puts " curl -G -H 'X-Api-Version: 1' http://localhost:9292/users \\"
|
|
48
|
+
puts " --data-urlencode \"filters=last_name=L*\" \\"
|
|
49
|
+
puts " --data-urlencode \"pagination=by=first_name,items=5\" \\"
|
|
50
|
+
puts " --data-urlencode \"order=-first_name\" \\"
|
|
51
|
+
puts " --data-urlencode \"fields=id,first_name,last_name,email\""
|
|
52
|
+
puts " (Note: To list all routes use: bundle exec rake praxis:routes)"
|
|
53
|
+
puts
|
|
167
54
|
nil
|
|
168
55
|
end
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
def generate_app_definitions_hello_world
|
|
172
|
-
create_file path('design/api.rb') do
|
|
173
|
-
<<-RUBY
|
|
174
|
-
# Use this file to define your response templates and traits.
|
|
175
|
-
#
|
|
176
|
-
# For example, to define a response template:
|
|
177
|
-
# response_template :custom do |media_type:|
|
|
178
|
-
# status 200
|
|
179
|
-
# media_type media_type
|
|
180
|
-
# end
|
|
181
|
-
Praxis::ApiDefinition.define do
|
|
182
|
-
# Trait that when included will require a Bearer authorization header to be passed in.
|
|
183
|
-
trait :authorized do
|
|
184
|
-
headers do
|
|
185
|
-
key "Authorization", String, regexp: /^.*Bearer\s/, required: true
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
|
189
|
-
RUBY
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
create_file path('design/resources/hello.rb') do
|
|
193
|
-
<<-RUBY
|
|
194
|
-
module V1
|
|
195
|
-
module ApiResources
|
|
196
|
-
class Hello
|
|
197
|
-
include Praxis::ResourceDefinition
|
|
198
|
-
|
|
199
|
-
media_type V1::MediaTypes::Hello
|
|
200
|
-
version '1.0'
|
|
201
|
-
|
|
202
|
-
prefix '/api/hello'
|
|
203
|
-
|
|
204
|
-
# Will apply to all actions of this resource
|
|
205
|
-
trait :authorized
|
|
206
|
-
|
|
207
|
-
action_defaults do
|
|
208
|
-
response :ok
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
action :index do
|
|
212
|
-
|
|
213
|
-
routing do
|
|
214
|
-
get ''
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
action :show do
|
|
219
|
-
|
|
220
|
-
routing do
|
|
221
|
-
get '/:id'
|
|
222
|
-
end
|
|
223
|
-
params do
|
|
224
|
-
attribute :id, Integer, required: true, min: 0
|
|
225
|
-
end
|
|
226
|
-
response :not_found
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
RUBY
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
create_file path('design/media_types/hello.rb') do
|
|
235
|
-
<<-RUBY
|
|
236
|
-
module V1
|
|
237
|
-
module MediaTypes
|
|
238
|
-
class Hello < Praxis::MediaType
|
|
239
|
-
|
|
240
|
-
identifier 'application/json'
|
|
241
|
-
|
|
242
|
-
attributes do
|
|
243
|
-
attribute :string, String
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
view :default do
|
|
247
|
-
attribute :string
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
RUBY
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
def generate_app_controllers_hello_world
|
|
258
|
-
create_file path('app/controllers/hello.rb') do
|
|
259
|
-
<<-RUBY
|
|
260
|
-
module V1
|
|
261
|
-
class Hello
|
|
262
|
-
include Praxis::Controller
|
|
263
|
-
|
|
264
|
-
implements V1::ApiResources::Hello
|
|
265
|
-
|
|
266
|
-
HELLO_WORLD = [ 'Hello world!', 'Привет мир!', 'Hola mundo!', '你好世界!', 'こんにちは世界!' ]
|
|
267
|
-
|
|
268
|
-
def index(**params)
|
|
269
|
-
response.headers['Content-Type'] = 'application/json'
|
|
270
|
-
response.body = HELLO_WORLD.to_json
|
|
271
|
-
response
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def show(id:, **other_params)
|
|
275
|
-
hello = HELLO_WORLD[id]
|
|
276
|
-
if hello
|
|
277
|
-
response.body = { id: id, data: hello }
|
|
278
|
-
else
|
|
279
|
-
self.response = Praxis::Responses::NotFound.new(body: "Hello word with index \#{id} not found in our DB")
|
|
280
|
-
end
|
|
281
|
-
response.headers['Content-Type'] = 'application/json'
|
|
282
|
-
response
|
|
283
|
-
end
|
|
284
56
|
end
|
|
285
57
|
end
|
|
286
|
-
RUBY
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
end
|
|
291
|
-
end
|
data/tasks/thor/model.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PraxisGen
|
|
4
|
+
class Model < Thor
|
|
5
|
+
require 'active_support/inflector'
|
|
6
|
+
include Thor::Actions
|
|
7
|
+
|
|
8
|
+
def self.source_root
|
|
9
|
+
File.dirname(__FILE__) + "/templates/generator/scaffold"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc "gmodel", "Generates a skeleton model file under app/models for ActiveRecord or Sequel."
|
|
13
|
+
argument :model_name, required: true
|
|
14
|
+
option :orm, required: false, default: 'activerecord', enum: ['activerecord','sequel']
|
|
15
|
+
def g
|
|
16
|
+
#self.class.check_name(model_name)
|
|
17
|
+
template_file = \
|
|
18
|
+
if options[:orm] == 'activerecord'
|
|
19
|
+
'models/active_record.rb'
|
|
20
|
+
else
|
|
21
|
+
'models/sequel.rb'
|
|
22
|
+
end
|
|
23
|
+
puts "Generating Model for #{model_name}"
|
|
24
|
+
template template_file, "app/models/#{model_name}.rb"
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
# Helper functions (which are available in the ERB contexts)
|
|
28
|
+
no_commands do
|
|
29
|
+
def model_class
|
|
30
|
+
model_name.camelize
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# TODO: do we want the argument to be camelcase? or snake case?
|
|
35
|
+
def self.check_name(name)
|
|
36
|
+
sanitized = name.downcase.gsub(/[^a-z0-9_]/, '')
|
|
37
|
+
raise "Please use only downcase letters, numbers and underscores for the model" unless sanitized == name
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PraxisGen
|
|
4
|
+
class Scaffold < Thor
|
|
5
|
+
require 'active_support/inflector'
|
|
6
|
+
include Thor::Actions
|
|
7
|
+
|
|
8
|
+
attr_reader :actions_hash
|
|
9
|
+
|
|
10
|
+
def self.source_root
|
|
11
|
+
File.dirname(__FILE__) + "/templates/generator/scaffold"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc "g","Generates an API design and implementation scaffold for managing a collection of <collection_name>"
|
|
15
|
+
argument :collection_name, required: true
|
|
16
|
+
option :version, required: false, default: '1',
|
|
17
|
+
desc: 'Version string for the API endpoint. This also dictates the directory structure (i.e., v1/endpoints/...))'
|
|
18
|
+
option :design, type: :boolean, default: true,
|
|
19
|
+
desc: 'Include the Endpoint and MediaType files for the collection'
|
|
20
|
+
option :implementation, type: :boolean, default: true,
|
|
21
|
+
desc: 'Include the Controller and (possibly the) Resource files for the collection (see --no-resource)'
|
|
22
|
+
option :resource, type: :boolean, default: true,
|
|
23
|
+
desc: 'Disable (or enable) the creation of the Resource files when generating implementation'
|
|
24
|
+
option :model, type: :string, enum: ['activerecord','sequel'],
|
|
25
|
+
desc: 'It also generates a model for the given ORM. An empty --model flag will default to activerecord'
|
|
26
|
+
option :actions, type: :string, default: 'crud', enum: ['cr','cru','crud','u','ud','d'],
|
|
27
|
+
desc: 'Specifies the actions to generate for the API. cr=create, u=update, d=delete. Index and show actions are always generated'
|
|
28
|
+
def g
|
|
29
|
+
self.class.check_name(collection_name)
|
|
30
|
+
@actions_hash = self.class.compose_actions_hash(options[:actions])
|
|
31
|
+
env_rb = Pathname.new(destination_root)+Pathname.new("config/environment.rb")
|
|
32
|
+
@pagination_plugin_found = File.open(env_rb).grep(/Praxis::Plugins::PaginationPlugin.*/).reject{|l| l.strip[0] == '#'}.present?
|
|
33
|
+
if options[:design]
|
|
34
|
+
say_status 'Design', "Generating scaffold for #{plural_class}", :blue
|
|
35
|
+
template 'design/media_types/item.rb', "design/#{version_dir}/media_types/#{collection_name.singularize}.rb"
|
|
36
|
+
template 'design/endpoints/collection.rb', "design/#{version_dir}/endpoints/#{collection_name}.rb"
|
|
37
|
+
end
|
|
38
|
+
if options[:implementation]
|
|
39
|
+
say_status 'Implement', "Generating scaffold for #{plural_class}", :blue
|
|
40
|
+
if options[:resource]
|
|
41
|
+
base_resource = Pathname.new(destination_root)+Pathname.new("app/#{version_dir}/resources/base.rb")
|
|
42
|
+
unless base_resource.exist?
|
|
43
|
+
# Copy an appropriate base resource for the version (resources within same version must share same base)
|
|
44
|
+
say_status "NOTE:",
|
|
45
|
+
"Creating a base resource file for resources to inherit from (at 'app/#{version_dir}/resources/base.rb')",
|
|
46
|
+
:yellow
|
|
47
|
+
say_status "",
|
|
48
|
+
"If you had already other resources in the app, change them to derive from this Base"
|
|
49
|
+
template 'implementation/resources/base.rb', "app/#{version_dir}/resources/base.rb"
|
|
50
|
+
end
|
|
51
|
+
template 'implementation/resources/item.rb', "app/#{version_dir}/resources/#{collection_name.singularize}.rb"
|
|
52
|
+
end
|
|
53
|
+
template 'implementation/controllers/collection.rb', "app/#{version_dir}/controllers/#{collection_name}.rb"
|
|
54
|
+
end
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Helper functions (which are available in the ERB contexts)
|
|
59
|
+
no_commands do
|
|
60
|
+
def plural_class
|
|
61
|
+
collection_name.camelize
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def singular_class
|
|
65
|
+
collection_name.singularize.camelize
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def version
|
|
69
|
+
options[:version]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def version_module
|
|
73
|
+
"V#{version}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def version_dir
|
|
77
|
+
version_module.camelize(:lower)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def action_enabled?(action)
|
|
81
|
+
@actions_hash[action.to_sym]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def pagination_enabled?
|
|
85
|
+
@pagination_plugin_found
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.compose_actions_hash(actions_opt)
|
|
90
|
+
required = { index: true, show: true }
|
|
91
|
+
case actions_opt
|
|
92
|
+
when nil
|
|
93
|
+
required
|
|
94
|
+
when 'cr'
|
|
95
|
+
required.merge(create: true)
|
|
96
|
+
when 'cru'
|
|
97
|
+
required.merge(create: true, update: true)
|
|
98
|
+
when 'crud'
|
|
99
|
+
required.merge(create: true, update: true, delete: true)
|
|
100
|
+
when 'u'
|
|
101
|
+
required.merge(update: true)
|
|
102
|
+
when 'ud'
|
|
103
|
+
required.merge(update: true, delete: true)
|
|
104
|
+
when 'd'
|
|
105
|
+
required.merge(delete: true)
|
|
106
|
+
else
|
|
107
|
+
raise "actions option does not support the string #{actions_opt}"
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.check_name(name)
|
|
112
|
+
sanitized = name.downcase.gsub(/[^a-z0-9_]/, '')
|
|
113
|
+
# TODO: bail or support CamelCase collections (for now only snake case)
|
|
114
|
+
raise "Please use only downcase letters, numbers and underscores for the collection" unless sanitized == name
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|