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.
Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +1 -3
  5. data/CHANGELOG.md +33 -0
  6. data/TODO.md +1 -4
  7. data/bin/praxis +67 -12
  8. data/lib/praxis.rb +10 -3
  9. data/lib/praxis/action_definition.rb +15 -13
  10. data/lib/praxis/action_definition/headers_dsl_compiler.rb +0 -7
  11. data/lib/praxis/api_general_info.rb +1 -1
  12. data/lib/praxis/application.rb +6 -2
  13. data/lib/praxis/blueprint.rb +357 -0
  14. data/lib/praxis/bootloader.rb +9 -3
  15. data/lib/praxis/bootloader_stages/environment.rb +16 -13
  16. data/lib/praxis/collection.rb +1 -11
  17. data/lib/praxis/config_hash.rb +44 -0
  18. data/lib/praxis/docs/{openapi → open_api}/info_object.rb +18 -10
  19. data/lib/praxis/docs/{openapi → open_api}/media_type_object.rb +0 -0
  20. data/lib/praxis/docs/{openapi → open_api}/operation_object.rb +0 -0
  21. data/lib/praxis/docs/{openapi → open_api}/parameter_object.rb +0 -0
  22. data/lib/praxis/docs/{openapi → open_api}/paths_object.rb +0 -0
  23. data/lib/praxis/docs/{openapi → open_api}/request_body_object.rb +0 -0
  24. data/lib/praxis/docs/{openapi → open_api}/response_object.rb +0 -0
  25. data/lib/praxis/docs/{openapi → open_api}/responses_object.rb +0 -0
  26. data/lib/praxis/docs/{openapi → open_api}/schema_object.rb +0 -0
  27. data/lib/praxis/docs/{openapi → open_api}/server_object.rb +0 -0
  28. data/lib/praxis/docs/{openapi → open_api}/tag_object.rb +0 -0
  29. data/lib/praxis/docs/open_api_generator.rb +91 -6
  30. data/lib/praxis/endpoint_definition.rb +273 -0
  31. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +182 -58
  32. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +3 -2
  33. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +47 -56
  34. data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +153 -0
  35. data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +20 -8
  36. data/lib/praxis/extensions/field_expansion.rb +3 -36
  37. data/lib/praxis/extensions/pagination.rb +5 -32
  38. data/lib/praxis/extensions/pagination/ordering_params.rb +1 -1
  39. data/lib/praxis/extensions/pagination/pagination_params.rb +6 -4
  40. data/lib/praxis/field_expander.rb +90 -0
  41. data/lib/praxis/finalizable.rb +34 -0
  42. data/lib/praxis/mapper/active_model_compat.rb +4 -0
  43. data/lib/praxis/mapper/resource.rb +18 -2
  44. data/lib/praxis/mapper/selector_generator.rb +2 -1
  45. data/lib/praxis/mapper/sequel_compat.rb +7 -0
  46. data/lib/praxis/media_type.rb +3 -68
  47. data/lib/praxis/plugin_concern.rb +1 -1
  48. data/lib/praxis/plugins/mapper_plugin.rb +24 -15
  49. data/lib/praxis/plugins/pagination_plugin.rb +34 -4
  50. data/lib/praxis/renderer.rb +88 -0
  51. data/lib/praxis/request.rb +1 -1
  52. data/lib/praxis/resource_definition.rb +2 -311
  53. data/lib/praxis/response_definition.rb +2 -10
  54. data/lib/praxis/response_template.rb +3 -3
  55. data/lib/praxis/router.rb +2 -2
  56. data/lib/praxis/routing_config.rb +1 -1
  57. data/lib/praxis/tasks/api_docs.rb +17 -64
  58. data/lib/praxis/tasks/routes.rb +1 -1
  59. data/lib/praxis/types/media_type_common.rb +1 -11
  60. data/lib/praxis/version.rb +1 -1
  61. data/praxis.gemspec +0 -1
  62. data/spec/functional_spec.rb +5 -9
  63. data/spec/praxis/action_definition_spec.rb +12 -20
  64. data/spec/praxis/blueprint_spec.rb +373 -0
  65. data/spec/praxis/bootloader_spec.rb +10 -2
  66. data/spec/praxis/collection_spec.rb +0 -13
  67. data/spec/praxis/config_hash_spec.rb +64 -0
  68. data/spec/praxis/{resource_definition_spec.rb → endpoint_definition_spec.rb} +37 -64
  69. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +249 -168
  70. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +25 -6
  71. data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +190 -8
  72. data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +140 -0
  73. data/spec/praxis/extensions/field_expansion_spec.rb +5 -24
  74. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +1 -1
  75. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +1 -1
  76. data/spec/praxis/extensions/support/spec_resources_active_model.rb +1 -1
  77. data/spec/praxis/field_expander_spec.rb +149 -0
  78. data/spec/praxis/mapper/selector_generator_spec.rb +1 -1
  79. data/spec/praxis/media_type_identifier_spec.rb +5 -4
  80. data/spec/praxis/media_type_spec.rb +4 -93
  81. data/spec/praxis/renderer_spec.rb +188 -0
  82. data/spec/praxis/response_definition_spec.rb +0 -31
  83. data/spec/praxis/response_spec.rb +1 -1
  84. data/spec/praxis/router_spec.rb +8 -8
  85. data/spec/praxis/routing_config_spec.rb +3 -3
  86. data/spec/spec_app/app/controllers/instances.rb +13 -7
  87. data/spec/spec_app/design/media_types/instance.rb +1 -19
  88. data/spec/spec_app/design/media_types/volume.rb +1 -1
  89. data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -14
  90. data/spec/spec_app/design/resources/instances.rb +5 -8
  91. data/spec/spec_app/design/resources/volume_snapshots.rb +1 -1
  92. data/spec/spec_app/design/resources/volumes.rb +1 -1
  93. data/spec/support/spec_authorization_plugin.rb +1 -1
  94. data/spec/support/spec_blueprints.rb +72 -0
  95. data/spec/support/{spec_resource_definitions.rb → spec_endpoint_definitions.rb} +2 -2
  96. data/spec/support/spec_media_types.rb +6 -26
  97. data/tasks/thor/app.rb +8 -34
  98. data/tasks/thor/example.rb +51 -285
  99. data/tasks/thor/model.rb +40 -0
  100. data/tasks/thor/scaffold.rb +117 -0
  101. data/tasks/thor/templates/generator/empty_app/.gitignore +0 -1
  102. data/tasks/thor/templates/generator/empty_app/Gemfile +7 -23
  103. data/tasks/thor/templates/generator/empty_app/README.md +1 -1
  104. data/tasks/thor/templates/generator/empty_app/Rakefile +4 -13
  105. data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.empty_directory +0 -0
  106. data/tasks/thor/templates/generator/empty_app/{design/response_templates → app/v1/resources}/.gitkeep +0 -0
  107. data/tasks/thor/templates/generator/empty_app/config/environment.rb +26 -17
  108. data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.empty_directory +0 -0
  109. data/tasks/thor/templates/generator/empty_app/{design/v1/resources → config/initializers}/.gitkeep +0 -0
  110. data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.empty_directory +0 -0
  111. data/tasks/thor/templates/generator/empty_app/design/v1/endpoints/.gitkeep +0 -0
  112. data/tasks/thor/templates/generator/empty_app/docs/.empty_directory +0 -0
  113. data/tasks/thor/templates/generator/empty_app/docs/.gitkeep +0 -0
  114. data/tasks/thor/templates/generator/empty_app/spec/spec_helper.rb +14 -9
  115. data/tasks/thor/templates/generator/example_app/.gitignore +1 -0
  116. data/tasks/thor/templates/generator/example_app/Gemfile +19 -0
  117. data/tasks/thor/templates/generator/example_app/Rakefile +61 -0
  118. data/tasks/thor/templates/generator/example_app/app/models/user.rb +6 -0
  119. data/tasks/thor/templates/generator/example_app/app/v1/concerns/controller_base.rb +24 -0
  120. data/tasks/thor/templates/generator/example_app/app/v1/controllers/users.rb +17 -0
  121. data/tasks/thor/templates/generator/example_app/app/v1/resources/base.rb +11 -0
  122. data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +25 -0
  123. data/tasks/thor/templates/generator/example_app/config.ru +30 -0
  124. data/tasks/thor/templates/generator/example_app/config/environment.rb +41 -0
  125. data/tasks/thor/templates/generator/example_app/db/migrate/20201010101010_create_users_table.rb +12 -0
  126. data/tasks/thor/templates/generator/example_app/db/seeds.rb +6 -0
  127. data/tasks/thor/templates/generator/example_app/design/api.rb +18 -0
  128. data/tasks/thor/templates/generator/example_app/design/v1/endpoints/users.rb +37 -0
  129. data/tasks/thor/templates/generator/example_app/design/v1/media_types/user.rb +21 -0
  130. data/tasks/thor/templates/generator/example_app/spec/helpers/database_helper.rb +20 -0
  131. data/tasks/thor/templates/generator/example_app/spec/spec_helper.rb +42 -0
  132. data/tasks/thor/templates/generator/example_app/spec/v1/controllers/users_spec.rb +37 -0
  133. data/tasks/thor/templates/generator/scaffold/design/endpoints/collection.rb +98 -0
  134. data/tasks/thor/templates/generator/scaffold/design/media_types/item.rb +18 -0
  135. data/tasks/thor/templates/generator/scaffold/implementation/controllers/collection.rb +77 -0
  136. data/tasks/thor/templates/generator/scaffold/implementation/resources/base.rb +11 -0
  137. data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +45 -0
  138. data/tasks/thor/templates/generator/scaffold/models/active_record.rb +6 -0
  139. data/tasks/thor/templates/generator/scaffold/models/sequel.rb +6 -0
  140. metadata +64 -136
  141. data/lib/api_browser/.bowerrc +0 -3
  142. data/lib/api_browser/.editorconfig +0 -21
  143. data/lib/api_browser/Gruntfile.js +0 -581
  144. data/lib/api_browser/app/index.html +0 -59
  145. data/lib/api_browser/app/js/app.js +0 -48
  146. data/lib/api_browser/app/js/controllers/action.js +0 -47
  147. data/lib/api_browser/app/js/controllers/controller.js +0 -10
  148. data/lib/api_browser/app/js/controllers/menu.js +0 -93
  149. data/lib/api_browser/app/js/controllers/trait.js +0 -10
  150. data/lib/api_browser/app/js/controllers/type.js +0 -24
  151. data/lib/api_browser/app/js/directives/attribute_description.js +0 -56
  152. data/lib/api_browser/app/js/directives/attribute_table.js +0 -28
  153. data/lib/api_browser/app/js/directives/conditional_requirements.js +0 -13
  154. data/lib/api_browser/app/js/directives/fixed_if_fits.js +0 -38
  155. data/lib/api_browser/app/js/directives/highlight.js +0 -14
  156. data/lib/api_browser/app/js/directives/menu_item.js +0 -59
  157. data/lib/api_browser/app/js/directives/no_container.js +0 -8
  158. data/lib/api_browser/app/js/directives/readable_list.js +0 -87
  159. data/lib/api_browser/app/js/directives/request_examples.js +0 -31
  160. data/lib/api_browser/app/js/directives/type_placeholder.js +0 -30
  161. data/lib/api_browser/app/js/directives/url.js +0 -15
  162. data/lib/api_browser/app/js/factories/Configuration.js +0 -12
  163. data/lib/api_browser/app/js/factories/Documentation.js +0 -61
  164. data/lib/api_browser/app/js/factories/Example.js +0 -51
  165. data/lib/api_browser/app/js/factories/PageInfo.js +0 -9
  166. data/lib/api_browser/app/js/factories/normalize_attributes.js +0 -20
  167. data/lib/api_browser/app/js/factories/prepare_template.js +0 -15
  168. data/lib/api_browser/app/js/factories/template_for.js +0 -128
  169. data/lib/api_browser/app/js/filters/attribute_name.js +0 -10
  170. data/lib/api_browser/app/js/filters/friendly_json.js +0 -5
  171. data/lib/api_browser/app/js/filters/has_requirement.js +0 -14
  172. data/lib/api_browser/app/js/filters/header_info.js +0 -9
  173. data/lib/api_browser/app/js/filters/is_empty.js +0 -8
  174. data/lib/api_browser/app/js/filters/markdown.js +0 -6
  175. data/lib/api_browser/app/js/filters/resource_name.js +0 -5
  176. data/lib/api_browser/app/js/filters/tag_requirement.js +0 -13
  177. data/lib/api_browser/app/sass/modules/_body.scss +0 -40
  178. data/lib/api_browser/app/sass/modules/_cloke.scss +0 -8
  179. data/lib/api_browser/app/sass/modules/_header.scss +0 -10
  180. data/lib/api_browser/app/sass/modules/_nav.scss +0 -7
  181. data/lib/api_browser/app/sass/modules/_sidebar.scss +0 -134
  182. data/lib/api_browser/app/sass/modules/_switch.scss +0 -55
  183. data/lib/api_browser/app/sass/modules/_table.scss +0 -13
  184. data/lib/api_browser/app/sass/praxis.scss +0 -70
  185. data/lib/api_browser/app/sass/variables/_bootstrap-variables.scss +0 -774
  186. data/lib/api_browser/app/views/action.html +0 -97
  187. data/lib/api_browser/app/views/builtin/field-selector.html +0 -24
  188. data/lib/api_browser/app/views/controller.html +0 -55
  189. data/lib/api_browser/app/views/directives/attribute_description.html +0 -2
  190. data/lib/api_browser/app/views/directives/attribute_description/default.html +0 -2
  191. data/lib/api_browser/app/views/directives/attribute_description/example.html +0 -13
  192. data/lib/api_browser/app/views/directives/attribute_description/headers.html +0 -8
  193. data/lib/api_browser/app/views/directives/attribute_description/member_options.html +0 -4
  194. data/lib/api_browser/app/views/directives/attribute_description/values.html +0 -14
  195. data/lib/api_browser/app/views/directives/attribute_table.html +0 -17
  196. data/lib/api_browser/app/views/directives/menu_item.html +0 -8
  197. data/lib/api_browser/app/views/directives/url.html +0 -3
  198. data/lib/api_browser/app/views/examples/general.html +0 -26
  199. data/lib/api_browser/app/views/home.html +0 -5
  200. data/lib/api_browser/app/views/layout.html +0 -8
  201. data/lib/api_browser/app/views/menu.html +0 -42
  202. data/lib/api_browser/app/views/navbar.html +0 -9
  203. data/lib/api_browser/app/views/trait.html +0 -13
  204. data/lib/api_browser/app/views/type.html +0 -6
  205. data/lib/api_browser/app/views/type/details.html +0 -33
  206. data/lib/api_browser/app/views/types/embedded/array.html +0 -2
  207. data/lib/api_browser/app/views/types/embedded/default.html +0 -12
  208. data/lib/api_browser/app/views/types/embedded/field-selector.html +0 -13
  209. data/lib/api_browser/app/views/types/embedded/links.html +0 -11
  210. data/lib/api_browser/app/views/types/embedded/requirements.html +0 -6
  211. data/lib/api_browser/app/views/types/embedded/single_req.html +0 -9
  212. data/lib/api_browser/app/views/types/embedded/struct.html +0 -14
  213. data/lib/api_browser/app/views/types/label/link.html +0 -1
  214. data/lib/api_browser/app/views/types/label/primitive.html +0 -1
  215. data/lib/api_browser/app/views/types/label/primitive_collection.html +0 -1
  216. data/lib/api_browser/app/views/types/label/type.html +0 -1
  217. data/lib/api_browser/app/views/types/label/type_collection.html +0 -1
  218. data/lib/api_browser/app/views/types/main/array.html +0 -22
  219. data/lib/api_browser/app/views/types/main/default.html +0 -23
  220. data/lib/api_browser/app/views/types/main/hash.html +0 -23
  221. data/lib/api_browser/app/views/types/standalone/array.html +0 -3
  222. data/lib/api_browser/app/views/types/standalone/default.html +0 -18
  223. data/lib/api_browser/app/views/types/standalone/struct.html +0 -2
  224. data/lib/api_browser/bower_template.json +0 -41
  225. data/lib/api_browser/package-lock.json +0 -7110
  226. data/lib/api_browser/package.json +0 -43
  227. data/lib/praxis/docs/generator.rb +0 -243
  228. data/lib/praxis/docs/link_builder.rb +0 -30
  229. data/lib/praxis/links.rb +0 -135
  230. data/lib/praxis/types/multipart.rb +0 -109
  231. data/spec/api_browser/directives/type_placeholder_spec.js +0 -134
  232. data/spec/api_browser/factories/configuration_spec.js +0 -32
  233. data/spec/api_browser/factories/documentation_spec.js +0 -100
  234. data/spec/api_browser/factories/normalize_attributes_spec.js +0 -92
  235. data/spec/api_browser/factories/template_for_spec.js +0 -67
  236. data/spec/api_browser/filters/attribute_name_spec.js +0 -23
  237. data/spec/praxis/types/multipart_spec.rb +0 -112
  238. data/tasks/thor/templates/generator/empty_app/.rspec +0 -1
  239. data/tasks/thor/templates/generator/empty_app/Guardfile +0 -3
  240. data/tasks/thor/templates/generator/empty_app/config/rainbows.rb +0 -57
  241. data/tasks/thor/templates/generator/empty_app/docs/app.js +0 -1
  242. data/tasks/thor/templates/generator/empty_app/docs/styles.scss +0 -3
@@ -1,5 +1,4 @@
1
1
  log
2
2
  .bundle
3
- api_docs
4
3
  docs/output
5
4
  docs/json
@@ -1,29 +1,13 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'praxis', github: 'praxis/praxis'
4
- gem 'attributor', github: 'praxis/attributor'
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 "rack-test", :require => "rack/test"
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
- platform :jruby do
28
- gem 'jruby-openssl'
29
- end
10
+ gem 'rake'
11
+ gem 'pry'
12
+ gem 'pry-byebug'
13
+ end
@@ -1,4 +1,4 @@
1
- Sample Blog Application
1
+ Example Application
2
2
  =======================
3
3
 
4
4
 
@@ -5,21 +5,12 @@ Bundler.require(:default, ENV['RACK_ENV'])
5
5
 
6
6
  require 'praxis/tasks'
7
7
 
8
- task :default => :spec
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
@@ -1,17 +1,26 @@
1
- #
2
- #Praxis::Application.instance.layout do
3
- # map :initializers, 'config/initializers/**/*'
4
- # map :lib, 'lib/**/*'
5
- # map :design, 'design/' do
6
- # map :api, 'api.rb'
7
- # map :media_types, '**/media_types/**/*'
8
- # map :resources, '**/resources/**/*'
9
- # end
10
- # map :app, 'app/' do
11
- # map :models, 'models/**/*'
12
- # map :controllers, '**/controllers/**/*'
13
- # map :responses, '**/responses/**/*'
14
- # end
15
- #end
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 :concerns, '**/concerns/**/*'
22
+ # map :resources, '**/resources/**/*'
23
+ # map :controllers, '**/controllers/**/*'
24
+ # end
25
+ # end
26
+ end
@@ -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
- Praxis::Blueprint.caching_enabled = true
9
- Praxis::Application.instance.setup
10
- end
7
+ # config.before(:suite) do
8
+ # Praxis::Blueprint.caching_enabled = true
9
+ # end
11
10
 
12
- config.before(:each) do
13
- Praxis::Blueprint.cache = Hash.new do |hash, key|
14
- hash[key] = Hash.new
15
- end
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,61 @@
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 'Fully receate, migrate and seed the DB'
36
+ task :recreate do
37
+ Rake::Task['db:drop'].invoke rescue nil
38
+ Rake::Task['db:create'].invoke
39
+ Rake::Task['db:migrate'].invoke
40
+ Rake::Task['db:seed'].invoke
41
+ end
42
+
43
+ desc 'seed with example data'
44
+ task seed: 'praxis:environment' do
45
+ require_relative 'db/seeds.rb'
46
+ end
47
+
48
+ desc 'drops current database'
49
+ task drop: 'praxis:environment' do
50
+ db_file = "development.sqlite3"
51
+ puts "Removing file #{db_file}"
52
+ `rm -f #{db_file}`
53
+ end
54
+
55
+ desc 'creates configured database'
56
+ task create: 'praxis:environment' do
57
+ puts "Creating file development.sqlite3"
58
+ ActiveRecord::Base.connection.execute("SELECT 1")
59
+ end
60
+ end
61
+
@@ -0,0 +1,6 @@
1
+
2
+ class User < ActiveRecord::Base
3
+ # So it can be used in all the automatic query/filtering extensions
4
+ include Praxis::Mapper::ActiveModelCompat
5
+
6
+ end
@@ -0,0 +1,24 @@
1
+ module V1
2
+ module Concerns
3
+ module ControllerBase
4
+ extend ActiveSupport::Concern
5
+ # Controller concen that wraps an API with a transaction, and automatically rolls it back
6
+ # for non-2xx (or 3xx) responses
7
+ included do
8
+ around :action do |controller, callee|
9
+ begin
10
+ # TODO: Support Sequel as well
11
+ ActiveRecord::Base.transaction do
12
+ callee.call
13
+ res = controller.response
14
+ # Force a rollback for non 2xx or 3xx responses
15
+ raise ActiveRecord::Rollback unless res.status >= 200 && res.status < 400
16
+ end
17
+ rescue ActiveRecord::Rollback
18
+ # No need to do anything, let the responses flow normally
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -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 Concerns::ControllerBase
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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module V1
4
+ module Resources
5
+ class Base < Praxis::Mapper::Resource
6
+ # Base for all V1 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,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module V1
4
+ module Resources
5
+ class User < Base
6
+ model ::User
7
+
8
+ # Mappings for the allowed filters
9
+ filters_mapping(
10
+ 'uuid': 'uuid',
11
+ 'first_name': 'first_name',
12
+ 'last_name': 'last_name',
13
+ 'email': 'email'
14
+ )
15
+
16
+ # To compute the full_name (method below) we need to load first and last names from the DB
17
+ property :full_name, dependencies: %i[first_name last_name]
18
+
19
+ # Computed attribute that combines first and last
20
+ def full_name
21
+ [first_name, last_name].join(' ')
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
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
+ require 'praxis/plugins/mapper_plugin'
12
+ require 'praxis/mapper/active_model_compat'
13
+ # Want to take advantage of the pagination and sorting extensions as well
14
+ require 'praxis/plugins/pagination_plugin'
15
+
16
+ # Start the sqlite DB
17
+ case ENV['RACK_ENV']
18
+ when 'test'
19
+ ActiveRecord::Base.establish_connection(
20
+ adapter: 'sqlite3',
21
+ database: ':memory:'
22
+ )
23
+ else
24
+ ActiveRecord::Base.establish_connection(
25
+ adapter: 'sqlite3',
26
+ database: "development.sqlite3"
27
+ )
28
+ end
29
+
30
+ run Praxis::Application.instance.setup
@@ -0,0 +1,41 @@
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
+ # Configure 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 :concerns, '**/concerns/**/*'
37
+ # map :resources, '**/resources/**/*'
38
+ # map :controllers, '**/controllers/**/*'
39
+ # end
40
+ # end
41
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateUsersTable < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :users do |table|
6
+ table.column :uuid, :string, null: false
7
+ table.column :first_name, :string, null: false
8
+ table.column :last_name, :string
9
+ table.column :email, :string
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+
2
+ require_relative '../spec/helpers/database_helper'
3
+ # Invoke the encapsulated seed class...
4
+ DatabaseHelper.seed!
5
+
6
+ # Add more seeds here..