praxis 2.0.pre.18 → 2.0.pre.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +54 -0
  3. data/.simplecov +3 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +6 -0
  6. data/CONTRIBUTING.md +2 -79
  7. data/Gemfile +5 -1
  8. data/Guardfile +6 -4
  9. data/LICENSE +0 -2
  10. data/MAINTAINERS.md +1 -0
  11. data/README.md +15 -22
  12. data/Rakefile +4 -2
  13. data/bin/praxis +55 -58
  14. data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -6
  15. data/lib/praxis/action_definition.rb +64 -94
  16. data/lib/praxis/api_definition.rb +21 -29
  17. data/lib/praxis/api_general_info.rb +55 -66
  18. data/lib/praxis/application.rb +15 -32
  19. data/lib/praxis/blueprint.rb +64 -73
  20. data/lib/praxis/bootloader.rb +24 -33
  21. data/lib/praxis/bootloader_stages/environment.rb +5 -10
  22. data/lib/praxis/bootloader_stages/file_loader.rb +3 -6
  23. data/lib/praxis/bootloader_stages/plugin_config_load.rb +4 -6
  24. data/lib/praxis/bootloader_stages/plugin_config_prepare.rb +2 -2
  25. data/lib/praxis/bootloader_stages/plugin_loader.rb +3 -7
  26. data/lib/praxis/bootloader_stages/plugin_setup.rb +3 -3
  27. data/lib/praxis/bootloader_stages/routing.rb +5 -8
  28. data/lib/praxis/bootloader_stages/subgroup_loader.rb +2 -10
  29. data/lib/praxis/bootloader_stages/warn_unloaded_files.rb +15 -19
  30. data/lib/praxis/callbacks.rb +12 -11
  31. data/lib/praxis/collection.rb +10 -13
  32. data/lib/praxis/config.rb +17 -28
  33. data/lib/praxis/config_hash.rb +2 -1
  34. data/lib/praxis/controller.rb +7 -6
  35. data/lib/praxis/dispatcher.rb +34 -42
  36. data/lib/praxis/docs/open_api/info_object.rb +11 -8
  37. data/lib/praxis/docs/open_api/media_type_object.rb +18 -17
  38. data/lib/praxis/docs/open_api/operation_object.rb +6 -3
  39. data/lib/praxis/docs/open_api/parameter_object.rb +17 -14
  40. data/lib/praxis/docs/open_api/paths_object.rb +11 -9
  41. data/lib/praxis/docs/open_api/request_body_object.rb +14 -13
  42. data/lib/praxis/docs/open_api/response_object.rb +24 -18
  43. data/lib/praxis/docs/open_api/responses_object.rb +3 -1
  44. data/lib/praxis/docs/open_api/schema_object.rb +16 -16
  45. data/lib/praxis/docs/open_api/server_object.rb +5 -2
  46. data/lib/praxis/docs/open_api/tag_object.rb +6 -3
  47. data/lib/praxis/docs/open_api_generator.rb +92 -95
  48. data/lib/praxis/endpoint_definition.rb +60 -77
  49. data/lib/praxis/error_handler.rb +2 -2
  50. data/lib/praxis/exception.rb +2 -0
  51. data/lib/praxis/exceptions/config.rb +3 -1
  52. data/lib/praxis/exceptions/config_load.rb +2 -0
  53. data/lib/praxis/exceptions/config_validation.rb +3 -1
  54. data/lib/praxis/exceptions/invalid_configuration.rb +3 -1
  55. data/lib/praxis/exceptions/invalid_response.rb +3 -1
  56. data/lib/praxis/exceptions/invalid_trait.rb +3 -1
  57. data/lib/praxis/exceptions/stage_not_found.rb +3 -1
  58. data/lib/praxis/exceptions/validation.rb +4 -3
  59. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +163 -149
  60. data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +18 -13
  61. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +13 -9
  62. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +14 -11
  63. data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +12 -9
  64. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +8 -5
  65. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +89 -65
  66. data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +68 -62
  67. data/lib/praxis/extensions/attribute_filtering.rb +3 -1
  68. data/lib/praxis/extensions/field_expansion.rb +6 -4
  69. data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +10 -8
  70. data/lib/praxis/extensions/field_selection/field_selector.rb +91 -92
  71. data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +12 -12
  72. data/lib/praxis/extensions/field_selection.rb +3 -1
  73. data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +6 -4
  74. data/lib/praxis/extensions/pagination/header_generator.rb +16 -11
  75. data/lib/praxis/extensions/pagination/ordering_params.rb +29 -28
  76. data/lib/praxis/extensions/pagination/pagination_handler.rb +44 -42
  77. data/lib/praxis/extensions/pagination/pagination_params.rb +29 -48
  78. data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +8 -7
  79. data/lib/praxis/extensions/pagination.rb +10 -15
  80. data/lib/praxis/extensions/rails_compat/request_methods.rb +3 -4
  81. data/lib/praxis/extensions/rails_compat.rb +2 -0
  82. data/lib/praxis/extensions/rendering.rb +12 -12
  83. data/lib/praxis/field_expander.rb +8 -9
  84. data/lib/praxis/file_group.rb +8 -12
  85. data/lib/praxis/finalizable.rb +1 -0
  86. data/lib/praxis/handlers/json.rb +5 -2
  87. data/lib/praxis/handlers/plain.rb +2 -1
  88. data/lib/praxis/handlers/www_form.rb +6 -3
  89. data/lib/praxis/handlers/{xml-sample.rb → xml_sample.rb} +26 -22
  90. data/lib/praxis/mapper/active_model_compat.rb +13 -10
  91. data/lib/praxis/mapper/resource.rb +171 -180
  92. data/lib/praxis/mapper/selector_generator.rb +106 -112
  93. data/lib/praxis/mapper/sequel_compat.rb +70 -67
  94. data/lib/praxis/media_type.rb +2 -2
  95. data/lib/praxis/media_type_identifier.rb +26 -22
  96. data/lib/praxis/middleware_app.rb +18 -15
  97. data/lib/praxis/multipart/parser.rb +46 -51
  98. data/lib/praxis/multipart/part.rb +78 -110
  99. data/lib/praxis/notifications.rb +2 -4
  100. data/lib/praxis/plugin.rb +11 -18
  101. data/lib/praxis/plugin_concern.rb +12 -15
  102. data/lib/praxis/plugins/mapper_plugin.rb +15 -13
  103. data/lib/praxis/plugins/pagination_plugin.rb +8 -6
  104. data/lib/praxis/plugins/rails_plugin.rb +33 -28
  105. data/lib/praxis/renderer.rb +11 -15
  106. data/lib/praxis/request.rb +46 -47
  107. data/lib/praxis/request_stages/action.rb +4 -6
  108. data/lib/praxis/request_stages/load_request.rb +2 -4
  109. data/lib/praxis/request_stages/request_stage.rb +19 -23
  110. data/lib/praxis/request_stages/response.rb +4 -6
  111. data/lib/praxis/request_stages/validate.rb +3 -5
  112. data/lib/praxis/request_stages/validate_params_and_headers.rb +15 -16
  113. data/lib/praxis/request_stages/validate_payload.rb +25 -27
  114. data/lib/praxis/request_superclassing.rb +3 -3
  115. data/lib/praxis/resource_definition.rb +1 -0
  116. data/lib/praxis/response.rb +13 -25
  117. data/lib/praxis/response_definition.rb +77 -122
  118. data/lib/praxis/response_template.rb +11 -15
  119. data/lib/praxis/responses/http.rb +23 -44
  120. data/lib/praxis/responses/internal_server_error.rb +18 -21
  121. data/lib/praxis/responses/multipart_ok.rb +4 -9
  122. data/lib/praxis/responses/validation_error.rb +8 -15
  123. data/lib/praxis/route.rb +8 -10
  124. data/lib/praxis/router/rack.rb +13 -7
  125. data/lib/praxis/router/simple.rb +10 -5
  126. data/lib/praxis/router.rb +27 -34
  127. data/lib/praxis/routing_config.rb +52 -29
  128. data/lib/praxis/simple_media_type.rb +5 -8
  129. data/lib/praxis/stage.rb +17 -25
  130. data/lib/praxis/tasks/api_docs.rb +15 -15
  131. data/lib/praxis/tasks/console.rb +3 -1
  132. data/lib/praxis/tasks/environment.rb +2 -0
  133. data/lib/praxis/tasks/routes.rb +26 -24
  134. data/lib/praxis/tasks.rb +3 -1
  135. data/lib/praxis/trait.rb +37 -46
  136. data/lib/praxis/types/fuzzy_hash.rb +13 -14
  137. data/lib/praxis/types/media_type_common.rb +11 -10
  138. data/lib/praxis/types/multipart_array/part_definition.rb +14 -17
  139. data/lib/praxis/types/multipart_array.rb +88 -112
  140. data/lib/praxis/validation_handler.rb +5 -3
  141. data/lib/praxis/version.rb +3 -1
  142. data/lib/praxis.rb +4 -5
  143. data/praxis.gemspec +22 -21
  144. data/spec/functional_spec.rb +40 -52
  145. data/spec/praxis/action_definition_spec.rb +36 -46
  146. data/spec/praxis/api_definition_spec.rb +45 -47
  147. data/spec/praxis/api_general_info_spec.rb +28 -29
  148. data/spec/praxis/application_spec.rb +18 -14
  149. data/spec/praxis/blueprint_spec.rb +33 -34
  150. data/spec/praxis/bootloader_spec.rb +32 -30
  151. data/spec/praxis/callbacks_spec.rb +37 -37
  152. data/spec/praxis/collection_spec.rb +18 -25
  153. data/spec/praxis/config_hash_spec.rb +5 -4
  154. data/spec/praxis/config_spec.rb +27 -26
  155. data/spec/praxis/controller_spec.rb +8 -9
  156. data/spec/praxis/endpoint_definition_spec.rb +25 -32
  157. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +171 -114
  158. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +22 -21
  159. data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +112 -60
  160. data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +37 -38
  161. data/spec/praxis/extensions/field_expansion_spec.rb +8 -10
  162. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +14 -13
  163. data/spec/praxis/extensions/field_selection/field_selector_spec.rb +9 -16
  164. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +50 -49
  165. data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +32 -31
  166. data/spec/praxis/extensions/rendering_spec.rb +9 -9
  167. data/spec/praxis/extensions/support/spec_resources_active_model.rb +32 -49
  168. data/spec/praxis/extensions/support/spec_resources_sequel.rb +48 -48
  169. data/spec/praxis/field_expander_spec.rb +6 -5
  170. data/spec/praxis/file_group_spec.rb +3 -1
  171. data/spec/praxis/handlers/json_spec.rb +6 -5
  172. data/spec/praxis/mapper/resource_spec.rb +27 -30
  173. data/spec/praxis/mapper/selector_generator_spec.rb +50 -50
  174. data/spec/praxis/media_type_identifier_spec.rb +13 -10
  175. data/spec/praxis/media_type_spec.rb +12 -12
  176. data/spec/praxis/middleware_app_spec.rb +23 -22
  177. data/spec/praxis/multipart/parser_spec.rb +7 -9
  178. data/spec/praxis/notifications_spec.rb +4 -4
  179. data/spec/praxis/plugin_concern_spec.rb +5 -6
  180. data/spec/praxis/renderer_spec.rb +10 -9
  181. data/spec/praxis/request_spec.rb +38 -41
  182. data/spec/praxis/request_stages/action_spec.rb +14 -15
  183. data/spec/praxis/request_stages/request_stage_spec.rb +30 -41
  184. data/spec/praxis/request_stages/validate_spec.rb +3 -1
  185. data/spec/praxis/response_definition_spec.rb +79 -92
  186. data/spec/praxis/response_spec.rb +28 -39
  187. data/spec/praxis/responses/internal_server_error_spec.rb +6 -9
  188. data/spec/praxis/responses/validation_error_spec.rb +17 -18
  189. data/spec/praxis/route_spec.rb +4 -7
  190. data/spec/praxis/router_spec.rb +69 -79
  191. data/spec/praxis/routing_config_spec.rb +15 -14
  192. data/spec/praxis/stage_spec.rb +56 -53
  193. data/spec/praxis/trait_spec.rb +17 -18
  194. data/spec/praxis/types/fuzzy_hash_spec.rb +11 -9
  195. data/spec/praxis/types/multipart_array/part_definition_spec.rb +3 -2
  196. data/spec/praxis/types/multipart_array_spec.rb +33 -48
  197. data/spec/spec_app/app/concerns/authenticated.rb +5 -5
  198. data/spec/spec_app/app/concerns/basic_api.rb +3 -1
  199. data/spec/spec_app/app/concerns/log_wrapper.rb +5 -3
  200. data/spec/spec_app/app/controllers/base_class.rb +6 -5
  201. data/spec/spec_app/app/controllers/instances.rb +31 -34
  202. data/spec/spec_app/app/controllers/volumes.rb +6 -6
  203. data/spec/spec_app/app/responses/multipart.rb +1 -2
  204. data/spec/spec_app/app/responses/other_response.rb +2 -2
  205. data/spec/spec_app/config/environment.rb +19 -6
  206. data/spec/spec_app/config.ru +4 -3
  207. data/spec/spec_app/design/api.rb +13 -15
  208. data/spec/spec_app/design/media_types/instance.rb +5 -5
  209. data/spec/spec_app/design/media_types/volume.rb +2 -1
  210. data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -1
  211. data/spec/spec_app/design/resources/instances.rb +9 -15
  212. data/spec/spec_app/design/resources/volume_snapshots.rb +4 -5
  213. data/spec/spec_app/design/resources/volumes.rb +4 -5
  214. data/spec/spec_helper.rb +11 -13
  215. data/spec/support/be_deep_equal_matcher.rb +5 -0
  216. data/spec/support/spec_authorization_plugin.rb +7 -12
  217. data/spec/support/spec_blueprints.rb +2 -1
  218. data/spec/support/spec_complex_authentication_plugin.rb +17 -34
  219. data/spec/support/spec_endpoint_definitions.rb +2 -3
  220. data/spec/support/spec_media_types.rb +28 -35
  221. data/spec/support/spec_resources.rb +20 -18
  222. data/spec/support/spec_simple_authentication_plugin.rb +5 -9
  223. data/tasks/loader.thor +4 -2
  224. data/tasks/thor/app.rb +7 -5
  225. data/tasks/thor/example.rb +23 -22
  226. data/tasks/thor/model.rb +7 -7
  227. data/tasks/thor/scaffold.rb +23 -23
  228. data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +0 -8
  229. data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +1 -2
  230. metadata +72 -84
  231. data/MAINTAINERS +0 -2
  232. data/TODO.md +0 -25
  233. data/spec/praxis/api_resource_spec.rb +0 -0
  234. data/spec/praxis/dispatcher_spec.rb +0 -0
  235. data/spec/spec_app/app/responses/bulk_response.rb +0 -0
@@ -1,15 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Praxis
2
4
  module Types
3
5
  class MultipartArray < Attributor::Collection
4
6
  class PartDefinition
5
-
6
- attr_accessor :payload_attribute
7
- attr_accessor :headers_attribute
8
- attr_accessor :filename_attribute
9
-
7
+ attr_accessor :payload_attribute, :headers_attribute, :filename_attribute
10
8
 
11
9
  def initialize(&block)
12
- self.instance_eval(&block)
10
+ instance_eval(&block)
13
11
  end
14
12
 
15
13
  def update_attribute(attribute, options, block)
@@ -17,17 +15,17 @@ module Praxis
17
15
  attribute.type.attributes(**options, &block)
18
16
  end
19
17
 
20
- def create_attribute(type=Attributor::Struct, **opts, &block)
18
+ def create_attribute(type = Attributor::Struct, **opts, &block)
21
19
  # TODO: how do we want to handle any referenced types?
22
- return Attributor::Attribute.new(type, opts, &block)
20
+ Attributor::Attribute.new(type, opts, &block)
23
21
  end
24
22
 
25
- def payload(type=Attributor::Struct, **opts, &block)
26
- #return @payload if !block_given? && type == Attributor::Struct
23
+ def payload(type = Attributor::Struct, **opts, &block)
24
+ # return @payload if !block_given? && type == Attributor::Struct
27
25
  @payload_attribute = create_attribute(type, **opts, &block)
28
26
  end
29
27
 
30
- def header(name, val=nil, **options)
28
+ def header(name, val = nil, **options)
31
29
  block = proc { header(name, val, **options) }
32
30
 
33
31
  if @headers_attribute
@@ -35,17 +33,16 @@ module Praxis
35
33
  else
36
34
  type = Attributor::Hash.of(key: String)
37
35
  @headers_attribute = create_attribute(type,
38
- dsl_compiler: Praxis::ActionDefinition::HeadersDSLCompiler,
39
- case_insensitive_load: false, # :(
40
- allow_extra: true,
41
- &block)
36
+ dsl_compiler: Praxis::ActionDefinition::HeadersDSLCompiler,
37
+ case_insensitive_load: false, # :(
38
+ allow_extra: true,
39
+ &block)
42
40
  end
43
41
  end
44
42
 
45
- def filename(type=String, **opts)
43
+ def filename(type = String, **opts)
46
44
  @filename_attribute = create_attribute(type, **opts)
47
45
  end
48
-
49
46
  end
50
47
  end
51
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'praxis/types/multipart_array/part_definition'
2
4
 
3
5
  module Praxis
@@ -12,6 +14,7 @@ module Praxis
12
14
  @identifier = MediaTypeIdentifier.load('multipart/form-data').freeze
13
15
 
14
16
  def self.inherited(klass)
17
+ super
15
18
  klass.instance_eval do
16
19
  @attributes = FuzzyHash.new
17
20
  @saved_blocks = []
@@ -26,38 +29,32 @@ module Praxis
26
29
  @part_attribute = nil
27
30
 
28
31
  @identifier = MediaTypeIdentifier.load('multipart/form-data').freeze
29
-
30
32
  end
31
33
  end
32
34
 
33
35
  class << self
34
- attr_reader :attributes
35
- attr_reader :multiple
36
- attr_reader :options
37
- attr_reader :identifier
36
+ attr_reader :attributes, :multiple, :options, :identifier
38
37
  end
39
38
 
40
39
  def self.constructable?
41
40
  true
42
41
  end
43
42
 
44
- def self.construct(constructor_block, _options={})
43
+ def self.construct(constructor_block, _options = {})
45
44
  Class.new(self, &constructor_block)
46
45
  end
47
46
 
48
- def self.name_type(type=nil)
47
+ def self.name_type(type = nil)
49
48
  return @name_type if type.nil?
50
49
 
51
50
  @name_type = Attributor.resolve_type type
52
51
  end
53
52
 
54
- def self.payload_type(type=nil, **opts, &block)
53
+ def self.payload_type(type = nil, **opts, &block)
55
54
  if type.nil?
56
- if block_given?
57
- type = Attributor::Struct
58
- else
59
- return @payload_type
60
- end
55
+ return @payload_type unless block_given?
56
+
57
+ type = Attributor::Struct
61
58
  end
62
59
  @payload_type = Attributor.resolve_type(type)
63
60
  @payload_attribute = Attributor::Attribute.new(@payload_type, **opts, &block)
@@ -70,13 +67,13 @@ module Praxis
70
67
  end
71
68
 
72
69
  def self.part_attribute
73
- @part_attribute ||= Attributor::Attribute.new(Praxis::MultipartPart, payload_attribute: self.payload_attribute)
70
+ @part_attribute ||= Attributor::Attribute.new(Praxis::MultipartPart, payload_attribute: payload_attribute)
74
71
  end
75
72
 
76
- def self.part(name, payload_type=nil, multiple: false, filename: false, **opts, &block)
73
+ def self.part(name, payload_type = nil, multiple: false, filename: false, **opts, &block)
77
74
  @attributes.default_proc = nil
78
75
 
79
- if name.kind_of?(Regexp)
76
+ if name.is_a?(Regexp)
80
77
  raise 'part with regexp name may not take :multiple option' if multiple
81
78
  raise 'part with regexp name may not be required' if opts[:required] == true
82
79
  end
@@ -85,9 +82,7 @@ module Praxis
85
82
 
86
83
  compiler = Attributor::DSLCompiler.new(self, **opts)
87
84
 
88
- if filename
89
- filename_attribute = compiler.define('filename', String, required: true)
90
- end
85
+ filename_attribute = compiler.define('filename', String, required: true) if filename
91
86
 
92
87
  if block_given?
93
88
  definition = PartDefinition.new(&block)
@@ -95,35 +90,31 @@ module Praxis
95
90
  header_attribute = definition.headers_attribute
96
91
  filename_attribute = definition.filename_attribute || filename_attribute
97
92
 
98
- self.attributes[name] = compiler.define(name, Praxis::MultipartPart,
99
- payload_attribute: payload_attribute,
100
- headers_attribute: header_attribute,
101
- filename_attribute: filename_attribute
102
- )
93
+ attributes[name] = compiler.define(name, Praxis::MultipartPart,
94
+ payload_attribute: payload_attribute,
95
+ headers_attribute: header_attribute,
96
+ filename_attribute: filename_attribute)
103
97
  else
104
98
  payload_attribute = compiler.define(name, payload_type || self.payload_type, **opts)
105
- self.attributes[name] = compiler.define(name, Praxis::MultipartPart,
106
- payload_attribute: payload_attribute,
107
- filename_attribute: filename_attribute
108
- )
99
+ attributes[name] = compiler.define(name, Praxis::MultipartPart,
100
+ payload_attribute: payload_attribute,
101
+ filename_attribute: filename_attribute)
109
102
  end
110
103
  end
111
104
 
112
- def self.file(name, payload_type=nil, filename: nil, **opts, &block)
113
- self.part(name, payload_type, filename: true, **opts, &block)
105
+ def self.file(name, payload_type = nil, **opts, &block)
106
+ part(name, payload_type, filename: true, **opts, &block)
114
107
  end
115
108
 
116
- def self.load(value, context=Attributor::DEFAULT_ROOT_CONTEXT, content_type:nil)
117
- return value if value.kind_of?(self) || value.nil?
109
+ def self.load(value, _context = Attributor::DEFAULT_ROOT_CONTEXT, content_type: nil)
110
+ return value if value.is_a?(self) || value.nil?
118
111
 
119
- if value.kind_of?(::String) && content_type.nil?
120
- raise ArgumentError, "content_type is required to load values of type String for #{Attributor.type_name(self)}"
121
- end
112
+ raise ArgumentError, "content_type is required to load values of type String for #{Attributor.type_name(self)}" if value.is_a?(::String) && content_type.nil?
122
113
 
123
- parser = Praxis::MultipartParser.new({'Content-Type' => content_type}, value)
114
+ parser = Praxis::MultipartParser.new({ 'Content-Type' => content_type }, value)
124
115
  preamble, parts = parser.parse
125
116
 
126
- instance = self.new
117
+ instance = new
127
118
  instance.push(*parts)
128
119
 
129
120
  instance.preamble = preamble
@@ -132,22 +123,23 @@ module Praxis
132
123
  instance
133
124
  end
134
125
 
135
- def self.example(context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
136
- example = self.new
126
+ def self.example(context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
127
+ example = new
128
+
129
+ attributes.each do |name, attribute|
130
+ next if name.is_a? Regexp
137
131
 
138
- self.attributes.each do |name, attribute|
139
- next if name.kind_of? Regexp
140
- sub_context = self.generate_subcontext(context, name)
132
+ sub_context = generate_subcontext(context, name)
141
133
 
142
134
  part = attribute.example(sub_context)
143
135
  part.name = name
144
136
  example.push part
145
137
 
146
- if self.multiple.include? name
147
- part = attribute.example(sub_context + ['2'])
148
- part.name = name
149
- example.push part
150
- end
138
+ next unless multiple.include? name
139
+
140
+ part = attribute.example(sub_context + ['2'])
141
+ part.name = name
142
+ example.push part
151
143
  end
152
144
 
153
145
  example
@@ -174,36 +166,35 @@ module Praxis
174
166
  # profileImage: # Part 3 (an image)
175
167
  # type: string
176
168
  # format: binary
177
- #
178
- # NOTE: not sure if this
179
- def self.as_openapi_request_body( attribute_options: {} )
169
+ #
170
+ # NOTE: not sure if this
171
+ def self.as_openapi_request_body(attribute_options: {})
180
172
  hash = { type: json_schema_type }
181
- opts = self.options.merge( attribute_options )
173
+ opts = options.merge(attribute_options)
182
174
  hash[:description] = opts[:description] if opts[:description]
183
175
  hash[:default] = opts[:default] if opts[:default]
184
176
 
185
- unless self.attributes.empty?
177
+ unless attributes.empty?
186
178
  props = {}
187
179
  encoding = {}
188
- self.attributes.each do |part_name, part_attribute|
180
+ attributes.each do |part_name, part_attribute|
189
181
  part_example = part_attribute.example
190
182
  key_to_use = part_name.is_a?(Regexp) ? part_name.source : part_name
191
-
192
- part_info = {}
183
+
193
184
  if (payload_attribute = part_attribute.options[:payload_attribute])
194
185
  props[key_to_use] = payload_attribute.as_json_schema(example: part_example.payload)
195
186
  end
196
- #{
187
+ # {
197
188
  # contentType: 'fff',
198
189
  # headers: {
199
190
  # custom1: 'safd'
200
191
  # }
201
- if (headers_attribute = part_attribute.options[:headers_attribute])
202
- # Does this 'Content-Type' string check work?...can it be a symbol? what does it mean anyway?
203
- encoding[key_to_use][:contentType] = headers_attribute['Content-Type'] if headers_attribute['Content-Type']
204
- # TODO?rethink? ...is this correct?: att a 'headers' key with some header schemas if this part have some
205
- encoding[key_to_use]['headers'] = headers_attribute.as_json_schema(example: part_example.headers)
206
- end
192
+ next unless (headers_attribute = part_attribute.options[:headers_attribute])
193
+
194
+ # Does this 'Content-Type' string check work?...can it be a symbol? what does it mean anyway?
195
+ encoding[key_to_use][:contentType] = headers_attribute['Content-Type'] if headers_attribute['Content-Type']
196
+ # TODO?rethink? ...is this correct?: att a 'headers' key with some header schemas if this part have some
197
+ encoding[key_to_use]['headers'] = headers_attribute.as_json_schema(example: part_example.headers)
207
198
  end
208
199
 
209
200
  hash[:properties] = props
@@ -212,27 +203,27 @@ module Praxis
212
203
  hash
213
204
  end
214
205
 
215
- def self.as_json_schema( shallow: false, example: nil, attribute_options: {} )
206
+ def self.as_json_schema(attribute_options: {}, **_other)
216
207
  as_openapi_request_body(attribute_options: attribute_options)
217
208
  end
218
209
 
219
- def self.describe(shallow=true, example: nil)
210
+ def self.describe(shallow = true, example: nil)
220
211
  type_name = Attributor.type_name(self)
221
212
  hash = {
222
213
  name: type_name.gsub(Attributor::MODULE_PREFIX_REGEX, ''),
223
- family: self.family,
224
- id: self.id
214
+ family: family,
215
+ id: id
225
216
  }
226
217
  hash[:example] = example if example
227
218
 
228
- hash[:part_name] = {type: name_type.describe(true)}
219
+ hash[:part_name] = { type: name_type.describe(true) }
229
220
 
230
221
  unless shallow
231
- hash[:attributes] = {} if self.attributes.keys.any? { |name| name.kind_of? String}
232
- hash[:pattern_attributes] = {} if self.attributes.keys.any? { |name| name.kind_of? Regexp}
222
+ hash[:attributes] = {} if attributes.keys.any? { |name| name.is_a? String }
223
+ hash[:pattern_attributes] = {} if attributes.keys.any? { |name| name.is_a? Regexp }
233
224
 
234
225
  if hash.key?(:attributes) || hash.key?(:pattern_attributes)
235
- self.describe_attributes(shallow, example: example).each do |name, sub_hash|
226
+ describe_attributes(shallow, example: example).each do |name, sub_hash|
236
227
  case name
237
228
  when String
238
229
  hash[:attributes][name] = sub_hash
@@ -241,38 +232,30 @@ module Praxis
241
232
  end
242
233
  end
243
234
  else
244
- hash[:part_payload] = {type: payload_type.describe(true)}
235
+ hash[:part_payload] = { type: payload_type.describe(true) }
245
236
  end
246
237
  end
247
238
  hash
248
239
  end
249
240
 
250
- def self.describe_attributes(shallow=true, example: nil)
251
- self.attributes.each_with_object({}) do |(part_name, part_attribute), parts|
241
+ def self.describe_attributes(shallow = true, example: nil)
242
+ attributes.each_with_object({}) do |(part_name, part_attribute), parts|
252
243
  sub_example = example.part(part_name) if example
253
- if sub_example && self.multiple.include?(part_name)
254
- sub_example = sub_example.first
255
- end
244
+ sub_example = sub_example.first if sub_example && multiple.include?(part_name)
256
245
 
257
246
  sub_hash = part_attribute.describe(shallow, example: sub_example)
258
247
 
259
-
260
248
  if (options = sub_hash.delete(:options))
261
249
  sub_hash[:options] = {}
262
- if self.multiple.include?(part_name)
263
- sub_hash[:options][:multiple] = true
264
- end
250
+ sub_hash[:options][:multiple] = true if multiple.include?(part_name)
265
251
 
266
- if (payload_attribute = options.delete :payload_attribute)
267
- if (required = payload_attribute.options[:required])
268
- sub_hash[:options][:required] = true
269
- end
252
+ if (payload_attribute = options.delete :payload_attribute) && payload_attribute.options[:required]
253
+ sub_hash[:options][:required] = true
270
254
  end
271
255
  end
272
256
 
273
257
  sub_hash[:type] = MultipartPart.describe(shallow, example: sub_example, options: part_attribute.options)
274
258
 
275
-
276
259
  parts[part_name] = sub_hash
277
260
  end
278
261
  end
@@ -281,14 +264,13 @@ module Praxis
281
264
  attr_reader :content_type
282
265
 
283
266
  def initialize(content_type: self.class.identifier.to_s)
267
+ super()
284
268
  self.content_type = content_type
285
269
  end
286
270
 
287
271
  def content_type=(content_type)
288
272
  @content_type = MediaTypeIdentifier.load(content_type)
289
- if @content_type.parameters.get('boundary').nil?
290
- @content_type.parameters.set 'boundary', 'Boundary_puppies'
291
- end
273
+ @content_type.parameters.set 'boundary', 'Boundary_puppies' if @content_type.parameters.get('boundary').nil?
292
274
  @content_type
293
275
  end
294
276
 
@@ -298,9 +280,7 @@ module Praxis
298
280
 
299
281
  def push(*parts, context: Attributor::DEFAULT_ROOT_CONTEXT)
300
282
  part, *rest = parts
301
- if rest.any?
302
- return self.push(part, context: context).push(*rest, context:context)
303
- end
283
+ return push(part, context: context).push(*rest, context: context) if rest.any?
304
284
 
305
285
  original_context = context
306
286
 
@@ -313,12 +293,10 @@ module Praxis
313
293
  # payload_attribute, otherwise we constrain the parts
314
294
  # to the defined names.
315
295
  attribute = if self.class.attributes.empty?
316
- self.class.part_attribute
317
- elsif (default_thingy = self.class.attributes[key])
318
- default_thingy
319
- else
320
- nil
321
- end
296
+ self.class.part_attribute
297
+ elsif (default_thingy = self.class.attributes[key])
298
+ default_thingy
299
+ end
322
300
 
323
301
  if attribute
324
302
  part.attribute = attribute
@@ -327,11 +305,11 @@ module Praxis
327
305
  return self << part
328
306
  elsif self.class.options[:case_insensitive_load]
329
307
  name = self.class.attributes.keys.find do |k|
330
- k.kind_of?(String) && key.downcase == k.downcase
308
+ k.is_a?(String) && key.downcase == k.downcase
331
309
  end
332
310
  if name
333
311
  part.name = name
334
- return self.push(part, context: original_context)
312
+ return push(part, context: original_context)
335
313
  end
336
314
  end
337
315
 
@@ -342,29 +320,29 @@ module Praxis
342
320
  if self.class.multiple.include?(name)
343
321
  self.select { |i| i.name == name }
344
322
  else
345
- self.find { |i| i.name == name }
323
+ find { |i| i.name == name }
346
324
  end
347
325
  end
348
326
 
349
327
  def part?(name)
350
- self.any?{ |i| i.name == name }
328
+ any? { |i| i.name == name }
351
329
  end
352
330
 
353
- def validate(context=Attributor::DEFAULT_ROOT_CONTEXT)
354
- errors = self.each_with_index.each_with_object([]) do |(part, idx), errors|
331
+ def validate(context = Attributor::DEFAULT_ROOT_CONTEXT)
332
+ errors = each_with_index.each_with_object([]) do |(part, idx), error_list|
355
333
  sub_context = if part.name
356
- self.class.generate_subcontext(context, part.name)
357
- else
358
- context + ["at(#{idx})"]
359
- end
334
+ self.class.generate_subcontext(context, part.name)
335
+ else
336
+ context + ["at(#{idx})"]
337
+ end
360
338
 
361
- errors.push *part.validate(sub_context)
339
+ error_list.push(*part.validate(sub_context))
362
340
  end
363
341
 
364
342
  self.class.attributes.each do |name, attribute|
365
343
  payload_attribute = attribute.options[:payload_attribute]
366
344
 
367
- if !self.part?(name)
345
+ if !part?(name)
368
346
  if payload_attribute.options[:required]
369
347
  sub_context = self.class.generate_subcontext(context, name)
370
348
  errors.push "Attribute #{Attributor.humanize_context(sub_context)} is required"
@@ -385,15 +363,13 @@ module Praxis
385
363
  def dump(**opts)
386
364
  boundary = content_type.parameters.get 'boundary'
387
365
 
388
- parts = self.collect do |part|
366
+ parts = collect do |part|
389
367
  part.dump(**opts)
390
368
  end
391
369
 
392
370
  all_entities = parts.join("\r\n--#{boundary}\r\n")
393
371
  "--#{boundary}\r\n#{all_entities}\r\n--#{boundary}--\r\n"
394
372
  end
395
-
396
-
397
373
  end
398
374
  end
399
375
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Praxis
2
4
  class ValidationHandler
3
-
4
5
  # Should return the Response to send back
5
- def handle!(summary:, request:, stage:, errors: nil, exception: nil, **opts)
6
+ def handle!(summary:, errors: nil, exception: nil, **opts)
7
+ opts.delete(:request)
8
+ opts.delete(:stage)
6
9
  Responses::ValidationError.new(summary: summary, errors: errors, exception: exception, **opts)
7
10
  end
8
-
9
11
  end
10
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Praxis
2
- VERSION = '2.0.pre.18'
4
+ VERSION = '2.0.pre.19'
3
5
  end
data/lib/praxis.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack'
2
4
  require 'attributor'
3
5
 
@@ -5,7 +7,7 @@ require 'active_support/concern'
5
7
  require 'praxis/request_superclassing'
6
8
  require 'active_support/inflector'
7
9
 
8
- $:.unshift File.dirname(__FILE__)
10
+ $LOAD_PATH.unshift File.dirname(__FILE__)
9
11
 
10
12
  require 'mime'
11
13
  module MIME
@@ -15,7 +17,6 @@ module MIME
15
17
  end
16
18
 
17
19
  module Praxis
18
-
19
20
  autoload :ActionDefinition, 'praxis/action_definition'
20
21
  autoload :ApiGeneralInfo, 'praxis/api_general_info'
21
22
  autoload :ApiDefinition, 'praxis/api_definition'
@@ -28,7 +29,7 @@ module Praxis
28
29
  autoload :ErrorHandler, 'praxis/error_handler'
29
30
  autoload :ValidationHandler, 'praxis/validation_handler'
30
31
  autoload :Exception, 'praxis/exception'
31
- autoload :FileGroup,'praxis/file_group'
32
+ autoload :FileGroup, 'praxis/file_group'
32
33
  autoload :Plugin, 'praxis/plugin'
33
34
  autoload :PluginConcern, 'praxis/plugin_concern'
34
35
  autoload :Request, 'praxis/request'
@@ -50,7 +51,6 @@ module Praxis
50
51
  autoload :Blueprint, 'praxis/blueprint'
51
52
  autoload :FieldExpander, 'praxis/field_expander'
52
53
  autoload :Renderer, 'praxis/renderer'
53
-
54
54
 
55
55
  autoload :Notifications, 'praxis/notifications'
56
56
  autoload :MiddlewareApp, 'praxis/middleware_app'
@@ -143,5 +143,4 @@ module Praxis
143
143
  require 'praxis/responses/internal_server_error'
144
144
  require 'praxis/responses/validation_error'
145
145
  require 'praxis/responses/multipart_ok'
146
-
147
146
  end
data/praxis.gemspec CHANGED
@@ -1,36 +1,38 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
 
4
6
  require 'praxis/version'
5
7
 
6
8
  Gem::Specification.new do |spec|
7
- spec.name = "praxis"
9
+ spec.name = 'praxis'
8
10
  spec.version = Praxis::VERSION
9
- spec.authors = ["Josep M. Blanquer","Dane Jensen"]
11
+ spec.authors = ['Josep M. Blanquer', 'Dane Jensen']
10
12
  spec.summary = 'Building APIs the way you want it.'
11
13
 
12
- spec.email = ["blanquer@gmail.com","dane.jensen@gmail.com"]
14
+ spec.email = ['blanquer@gmail.com', 'dane.jensen@gmail.com']
13
15
 
14
- spec.homepage = "https://github.com/praxis/praxis"
15
- spec.license = "MIT"
16
- spec.required_ruby_version = ">=2.1"
16
+ spec.homepage = 'https://github.com/praxis/praxis'
17
+ spec.license = 'MIT'
18
+ spec.required_ruby_version = '>=2.5'
17
19
 
18
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
19
21
  spec.files = `git ls-files -z`.split("\x0")
20
22
  spec.bindir = 'bin'
21
23
  spec.executables << 'praxis'
22
24
 
23
- spec.add_dependency 'rack', '>= 1'
24
- spec.add_dependency 'mustermann', '>=1.1', '<=2'
25
25
  spec.add_dependency 'activesupport', '>= 3'
26
- spec.add_dependency 'mime', '~> 0'
27
26
  spec.add_dependency 'attributor', '>= 6.0'
28
- spec.add_dependency 'thor'
27
+ spec.add_dependency 'mime', '~> 0'
28
+ spec.add_dependency 'mustermann', '>=1.1', '<=2'
29
+ spec.add_dependency 'rack', '>= 1'
29
30
  spec.add_dependency 'terminal-table', '~> 1.4'
31
+ spec.add_dependency 'thor'
30
32
 
31
33
  spec.add_development_dependency 'bundler'
32
34
  spec.add_development_dependency 'rake', '>= 12.3.3'
33
-
35
+
34
36
  if RUBY_PLATFORM !~ /java/
35
37
  spec.add_development_dependency 'pry'
36
38
  spec.add_development_dependency 'pry-byebug'
@@ -39,17 +41,16 @@ Gem::Specification.new do |spec|
39
41
  else
40
42
  spec.add_development_dependency 'jdbc-sqlite3'
41
43
  end
42
- spec.add_development_dependency 'rspec', '~> 3'
43
- spec.add_development_dependency 'rspec-its', '~> 1'
44
- spec.add_development_dependency 'rspec-collection_matchers', '~> 1'
44
+ spec.add_development_dependency 'coveralls'
45
+ spec.add_development_dependency 'fuubar', '~> 2'
45
46
  spec.add_development_dependency 'guard', '~> 2'
46
- spec.add_development_dependency 'guard-rspec', '~> 4'
47
47
  spec.add_development_dependency 'guard-bundler', '~> 2'
48
+ spec.add_development_dependency 'guard-rspec', '~> 4'
48
49
  spec.add_development_dependency 'rack-test', '~> 0'
49
- spec.add_development_dependency 'simplecov', '~> 0'
50
- spec.add_development_dependency 'fuubar', '~> 2'
51
- spec.add_development_dependency 'coveralls'
50
+ spec.add_development_dependency 'rspec', '~> 3'
51
+ spec.add_development_dependency 'rspec-collection_matchers', '~> 1'
52
+ spec.add_development_dependency 'rspec-its', '~> 1'
52
53
  # Just for the query selector extensions etc...
54
+ spec.add_development_dependency 'activerecord', '> 4','< 7'
53
55
  spec.add_development_dependency 'sequel', '~> 5'
54
- spec.add_development_dependency 'activerecord', '> 4'
55
56
  end