praxis 2.0.pre.8 → 2.0.pre.13

Sign up to get free protection for your applications and to get access to all the features.
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..