praxis 2.0.pre.17 → 2.0.pre.21

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 (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 +19 -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 +65 -95
  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 +80 -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 +11 -14
  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 +7 -4
  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 +61 -29
  45. data/lib/praxis/docs/open_api/server_object.rb +5 -2
  46. data/lib/praxis/docs/open_api/tag_object.rb +9 -6
  47. data/lib/praxis/docs/open_api_generator.rb +114 -150
  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 +196 -181
  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 +48 -44
  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 -22
  113. data/lib/praxis/request_stages/validate_payload.rb +25 -28
  114. data/lib/praxis/request_superclassing.rb +3 -3
  115. data/lib/praxis/resource_definition.rb +1 -0
  116. data/lib/praxis/response.rb +24 -26
  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 +17 -16
  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 +100 -115
  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 +44 -56
  145. data/spec/praxis/action_definition_spec.rb +39 -48
  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 +39 -29
  173. data/spec/praxis/mapper/selector_generator_spec.rb +80 -46
  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 +35 -40
  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 -17
  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 +6 -6
  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 +11 -17
  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 +5 -4
  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 +22 -16
  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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A RESTful action allows you to define the following:
2
4
  # - a payload structure
3
5
  # - a params structure
@@ -9,13 +11,7 @@
9
11
 
10
12
  module Praxis
11
13
  class ActionDefinition
12
-
13
- attr_reader :name
14
- attr_reader :endpoint_definition
15
- attr_reader :api_definition
16
- attr_reader :route
17
- attr_reader :responses
18
- attr_reader :traits
14
+ attr_reader :name, :endpoint_definition, :api_definition, :route, :responses, :traits
19
15
 
20
16
  # opaque hash of user-defined medata, used to decorate the definition,
21
17
  # and also available in the generated JSON documents
@@ -28,21 +24,19 @@ module Praxis
28
24
  @doc_decorations = []
29
25
 
30
26
  def self.decorate_docs(&callback)
31
- self.doc_decorations << callback
27
+ doc_decorations << callback
32
28
  end
33
29
 
34
- def initialize(name, endpoint_definition, **opts, &block)
30
+ def initialize(name, endpoint_definition, **_opts, &block)
35
31
  @name = name
36
32
  @endpoint_definition = endpoint_definition
37
- @responses = Hash.new
38
- @metadata = Hash.new
33
+ @responses = {}
34
+ @metadata = {}
39
35
  @route = nil
40
36
  @traits = []
41
37
 
42
- if (media_type = endpoint_definition.media_type)
43
- if media_type.kind_of?(Class) && media_type < Praxis::Types::MediaTypeCommon
44
- @reference_media_type = media_type
45
- end
38
+ if (media_type = endpoint_definition.media_type) && (media_type.is_a?(Class) && media_type < Praxis::Types::MediaTypeCommon)
39
+ @reference_media_type = media_type
46
40
  end
47
41
 
48
42
  version = endpoint_definition.version
@@ -59,13 +53,11 @@ module Praxis
59
53
 
60
54
  endpoint_definition.action_defaults.apply!(self)
61
55
 
62
- self.instance_eval(&block) if block_given?
56
+ instance_eval(&block) if block_given?
63
57
  end
64
58
 
65
59
  def trait(trait_name)
66
- unless ApiDefinition.instance.traits.has_key? trait_name
67
- raise Exceptions::InvalidTrait.new("Trait #{trait_name} not found in the system")
68
- end
60
+ raise Exceptions::InvalidTrait, "Trait #{trait_name} not found in the system" unless ApiDefinition.instance.traits.key? trait_name
69
61
 
70
62
  trait = ApiDefinition.instance.traits.fetch(trait_name)
71
63
  trait.apply!(self)
@@ -77,13 +69,11 @@ module Praxis
77
69
  attribute.type.attributes(**options, &block)
78
70
  end
79
71
 
80
- def response(name, type=nil, **args, &block)
72
+ def response(name, type = nil, **args, &block)
81
73
  if type
82
74
  # should verify type is a media type
83
75
 
84
- if block_given?
85
- type = type.construct(block)
86
- end
76
+ type = type.construct(block) if block_given?
87
77
 
88
78
  args[:media_type] = type
89
79
  end
@@ -92,27 +82,22 @@ module Praxis
92
82
  @responses[name] = template.compile(self, **args)
93
83
  end
94
84
 
95
- def create_attribute(type=Attributor::Struct, **opts, &block)
96
- unless opts.key?(:reference)
97
- opts[:reference] = @reference_media_type if @reference_media_type && block
98
- end
85
+ def create_attribute(type = Attributor::Struct, **opts, &block)
86
+ opts[:reference] = @reference_media_type if !opts.key?(:reference) && (@reference_media_type && block)
99
87
 
100
- return Attributor::Attribute.new(type, opts, &block)
88
+ Attributor::Attribute.new(type, opts, &block)
101
89
  end
102
90
 
103
- def params(type=Attributor::Struct, **opts, &block)
104
- return @params if !block && ( opts.nil? || opts.empty? ) && type == Attributor::Struct
91
+ def params(type = Attributor::Struct, **opts, &block)
92
+ return @params if !block && (opts.nil? || opts.empty?) && type == Attributor::Struct
105
93
 
106
- unless( opts.key? :required )
94
+ unless opts.key? :required
107
95
  opts[:required] = true # Make the payload required by default
108
96
  end
109
97
 
110
98
  if @params
111
- unless type == Attributor::Struct && @params.type < Attributor::Struct
112
- raise Exceptions::InvalidConfiguration.new(
113
- "Invalid type received for extending params: #{type.name}"
114
- )
115
- end
99
+ raise Exceptions::InvalidConfiguration, "Invalid type received for extending params: #{type.name}" unless type == Attributor::Struct && @params.type < Attributor::Struct
100
+
116
101
  update_attribute(@params, opts, block)
117
102
  else
118
103
  @params = create_attribute(type, **opts, &block)
@@ -121,66 +106,59 @@ module Praxis
121
106
  @params
122
107
  end
123
108
 
124
- def payload(type=Attributor::Struct, **opts, &block)
125
- return @payload if !block && ( opts.nil? || opts.empty? ) && type == Attributor::Struct
109
+ def payload(type = Attributor::Struct, **opts, &block)
110
+ return @payload if !block && (opts.nil? || opts.empty?) && type == Attributor::Struct
126
111
 
127
- unless( opts.key? :required )
128
- opts[:required] = true # Make the payload required by default
112
+ unless opts.key?(:required)
113
+ opts = { required: true, null: false }.merge(opts) # Make the payload required and non-nullable by default
129
114
  end
130
115
 
131
116
  if @payload
132
- unless type == Attributor::Struct && @payload.type < Attributor::Struct
133
- raise Exceptions::InvalidConfiguration.new(
134
- "Invalid type received for extending params: #{type.name}"
135
- )
136
- end
117
+ raise Exceptions::InvalidConfiguration, "Invalid type received for extending params: #{type.name}" unless type == Attributor::Struct && @payload.type < Attributor::Struct
118
+
137
119
  update_attribute(@payload, opts, block)
138
120
  else
139
121
  @payload = create_attribute(type, **opts, &block)
140
122
  end
141
123
  end
142
124
 
143
- def headers(type=nil, **opts, &block)
125
+ def headers(type = nil, **opts, &block)
144
126
  return @headers unless block
145
127
 
146
- unless( opts.key? :required )
128
+ unless opts.key? :required
147
129
  opts[:required] = true # Make the payload required by default
148
130
  end
149
131
 
150
132
  if @headers
151
133
  update_attribute(@headers, opts, block)
152
134
  else
153
- type = Attributor::Hash.of(key:String) unless type
135
+ type ||= Attributor::Hash.of(key: String)
154
136
  @headers = create_attribute(type,
155
137
  dsl_compiler: HeadersDSLCompiler, case_insensitive_load: true,
156
138
  **opts, &block)
157
139
 
158
140
  @headers
159
141
  end
160
- @precomputed_header_keys_for_rack = nil #clear memoized data
142
+ @precomputed_header_keys_for_rack = nil # clear memoized data
161
143
  end
162
144
 
163
145
  # Good optimization to avoid creating lots of strings and comparisons
164
146
  # on a per-request basis.
165
147
  # However, this is hacky, as it is rack-specific, and does not really belong here
166
148
  def precomputed_header_keys_for_rack
167
- @precomputed_header_keys_for_rack ||= begin
168
- @headers.attributes.keys.each_with_object(Hash.new) do |key,hash|
169
- name = key.to_s
170
- name = "HTTP_#{name.gsub('-','_').upcase}" unless ( name == "CONTENT_TYPE" || name == "CONTENT_LENGTH" )
171
- hash[name] = key
172
- end
149
+ @precomputed_header_keys_for_rack ||= @headers.attributes.keys.each_with_object({}) do |key, hash|
150
+ name = key.to_s
151
+ name = "HTTP_#{name.gsub('-', '_').upcase}" unless %w[CONTENT_TYPE CONTENT_LENGTH].include?(name)
152
+ hash[name] = key
173
153
  end
174
154
  end
175
155
 
176
-
177
156
  def routing(&block)
178
- @routing_config.instance_eval &block
157
+ @routing_config.instance_eval(&block)
179
158
 
180
159
  @route = @routing_config.route
181
160
  end
182
161
 
183
-
184
162
  def description(text = nil)
185
163
  @description = text if text
186
164
  @description
@@ -194,7 +172,7 @@ module Praxis
194
172
 
195
173
  query_string = URI.encode_www_form(hash[:query_params])
196
174
  url = hash[:url]
197
- url = [url,query_string].join('?') unless query_string.empty?
175
+ url = [url, query_string].join('?') unless query_string.empty?
198
176
 
199
177
  route_description[:example] = url
200
178
  route_description
@@ -219,24 +197,23 @@ module Praxis
219
197
  hash[:payload] = payload_description(example: payload_example)
220
198
  end
221
199
 
222
- hash[:responses] = responses.inject({}) do |memo, (response_name, response)|
200
+ hash[:responses] = responses.each_with_object({}) do |(_response_name, response), memo|
223
201
  memo[response.name] = response.describe(context: context)
224
- memo
225
202
  end
226
203
  hash[:traits] = traits if traits.any?
227
204
  # FIXME: change to :routes along with api browser
228
205
  # FIXME: change urls to url ... (along with the browser)
229
- hash[:urls] = [ ActionDefinition.url_description(route: route, params: self.params, params_example: params_example) ]
206
+ hash[:urls] = [ActionDefinition.url_description(route: route, params: params, params_example: params_example)]
230
207
  self.class.doc_decorations.each do |callback|
231
208
  callback.call(self, hash)
232
209
  end
233
210
  end
234
211
  end
235
212
 
236
- def headers_description(example: )
213
+ def headers_description(example:)
237
214
  output = headers.describe(example: example)
238
- required_headers = self.headers.attributes.select{|k,attr| attr.options && attr.options[:required] == true }
239
- output[:example] = required_headers.each_with_object({}) do | (name, attr), hash |
215
+ required_headers = headers.attributes.select { |_k, attr| attr.options && attr.options[:required] == true }
216
+ output[:example] = required_headers.each_with_object({}) do |(name, _attr), hash|
240
217
  hash[name] = example[name].to_s # Some simple types (like Boolean) can be used as header values, but must convert back to s
241
218
  end
242
219
  output
@@ -247,23 +224,23 @@ module Praxis
247
224
  if route.nil?
248
225
  warn "Warning: No route defined for #{endpoint_definition.name}##{name}."
249
226
  else
250
- route_params = route.path.
251
- named_captures.
252
- keys.
253
- collect(&:to_sym)
227
+ route_params = route.path
228
+ .named_captures
229
+ .keys
230
+ .collect(&:to_sym)
254
231
  end
255
232
 
256
233
  desc = params.describe(example: example)
257
- desc[:type][:attributes].keys.each do |k|
234
+ desc[:type][:attributes].each_key do |k|
258
235
  source = if route_params.include? k
259
- 'url'
260
- else
261
- 'query'
262
- end
236
+ 'url'
237
+ else
238
+ 'query'
239
+ end
263
240
  desc[:type][:attributes][k][:source] = source
264
241
  end
265
- required_params = desc[:type][:attributes].select{|k,v| v[:source] == 'query' && v[:required] == true }.keys
266
- phash = required_params.each_with_object({}) do | name, hash |
242
+ required_params = desc[:type][:attributes].select { |_k, v| v[:source] == 'query' && v[:required] == true }.keys
243
+ phash = required_params.each_with_object({}) do |name, hash|
267
244
  hash[name] = example[name]
268
245
  end
269
246
  desc[:example] = URI.encode_www_form(phash)
@@ -277,12 +254,10 @@ module Praxis
277
254
  # of the headers.
278
255
  def derive_content_type(example, handler_name)
279
256
  # MultipartArrays *must* use the provided content_type
280
- if example.kind_of? Praxis::Types::MultipartArray
281
- return MediaTypeIdentifier.load(example.content_type)
282
- end
257
+ return MediaTypeIdentifier.load(example.content_type) if example.is_a? Praxis::Types::MultipartArray
283
258
 
284
- _, content_type_attribute = self.headers && self.headers.attributes.find { |k,v| k.to_s =~ /^content[-_]{1}type$/i }
285
- if content_type_attribute && content_type_attribute.options.key?(:values)
259
+ _, content_type_attribute = headers&.attributes&.find { |k, _v| k.to_s =~ /^content[-_]{1}type$/i }
260
+ if content_type_attribute&.options&.key?(:values)
286
261
 
287
262
  # if any defined value match the preferred handler_name, return it
288
263
  content_type_attribute.options[:values].each do |ct|
@@ -295,18 +270,15 @@ module Praxis
295
270
 
296
271
  # and return that one if it already corresponds to a registered handler
297
272
  # otherwise, add the encoding
298
- if Praxis::Application.instance.handlers.include?(pick.handler_name)
299
- return pick
300
- else
301
- return pick + handler_name
302
- end
273
+ return pick if Praxis::Application.instance.handlers.include?(pick.handler_name)
274
+
275
+ return pick + handler_name
303
276
  end
304
277
 
305
278
  # generic default encoding
306
279
  MediaTypeIdentifier.load("application/#{handler_name}")
307
280
  end
308
281
 
309
-
310
282
  def payload_description(example:)
311
283
  hash = payload.describe(example: example)
312
284
 
@@ -322,11 +294,10 @@ module Praxis
322
294
 
323
295
  # in case handler is nil, use dumped_payload as-is.
324
296
  generated_payload = if handler.nil?
325
- dumped_payload
326
- else
327
- handler.generate(dumped_payload)
328
- end
329
-
297
+ dumped_payload
298
+ else
299
+ handler.generate(dumped_payload)
300
+ end
330
301
 
331
302
  hash[:examples][default_handler] = {
332
303
  content_type: content_type.to_s,
@@ -337,14 +308,13 @@ module Praxis
337
308
  hash
338
309
  end
339
310
 
340
-
341
311
  def nodoc!
342
312
  metadata[:doc_visibility] = :none
343
313
  end
344
314
 
345
- # [DEPRECATED] - Warn of the change of method name for the transition
315
+ # [DEPRECATED] - Warn of the change of method name for the transition
346
316
  def resource_definition
347
- raise "Praxis::ActionDefinition does not use `resource_definition` any longer. Use `endpoint_definition` instead."
317
+ raise 'Praxis::ActionDefinition does not use `resource_definition` any longer. Use `endpoint_definition` instead.'
348
318
  end
349
319
  end
350
320
  end
@@ -1,30 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require 'forwardable'
3
5
 
4
6
  module Praxis
5
-
6
7
  class ApiDefinition
7
8
  include Singleton
8
9
  extend Forwardable
9
10
 
10
- attr_reader :traits
11
- attr_reader :responses
12
- attr_reader :infos
13
- attr_reader :global_info
11
+ attr_reader :traits, :responses, :infos, :global_info
14
12
 
15
13
  attr_accessor :versioning_scheme
16
14
 
17
15
  def self.define(&block)
18
- if block.arity == 0
19
- self.instance.instance_eval(&block)
16
+ if block.arity.zero?
17
+ instance.instance_eval(&block)
20
18
  else
21
- yield(self.instance)
19
+ yield(instance)
22
20
  end
23
21
  end
24
22
 
25
23
  def initialize
26
- @responses = Hash.new
27
- @traits = Hash.new
24
+ @responses = {}
25
+ @traits = {}
28
26
  @base_path = ''
29
27
 
30
28
  @global_info = ApiGeneralInfo.new
@@ -39,20 +37,19 @@ module Praxis
39
37
  end
40
38
 
41
39
  def response(name)
42
- return @responses.fetch(name) do
40
+ @responses.fetch(name) do
43
41
  raise ArgumentError, "no response template defined with name #{name.inspect}. Are you forgetting to register it with ApiDefinition?"
44
42
  end
45
43
  end
46
44
 
47
45
  def trait(name, &block)
48
- if self.traits.has_key? name
49
- raise Exceptions::InvalidTrait.new("Overwriting a previous trait with the same name (#{name})")
50
- end
51
- self.traits[name] = Trait.new(&block)
46
+ raise Exceptions::InvalidTrait, "Overwriting a previous trait with the same name (#{name})" if traits.key? name
47
+
48
+ traits[name] = Trait.new(&block)
52
49
  end
53
50
 
54
51
  # Setting info to the nil version, means setting it for all versions (if they don't override them)
55
- def info(version=nil, &block)
52
+ def info(version = nil, &block)
56
53
  if version.nil?
57
54
  if block_given?
58
55
  @global_info.instance_eval(&block)
@@ -61,26 +58,23 @@ module Praxis
61
58
  end
62
59
  else
63
60
  i = @infos[version]
64
- if block_given?
65
- i.instance_eval(&block)
66
- end
61
+ i.instance_eval(&block) if block_given?
67
62
  i
68
63
  end
69
64
  end
70
65
 
71
66
  def describe
72
67
  data = Hash.new do |hash, version|
73
- hash[version] = Hash.new
68
+ hash[version] = {}
74
69
  end
75
70
 
76
71
  data[:global][:info] = @global_info.describe
77
72
 
78
73
  # Fill in the "info" portion
79
- @infos.each do |version,info|
74
+ @infos.each do |version, info|
80
75
  data[version][:info] = info.describe
81
76
  end
82
77
 
83
-
84
78
  if traits.any?
85
79
  data[:traits] = {}
86
80
  traits.each do |name, trait|
@@ -92,12 +86,12 @@ module Praxis
92
86
  end
93
87
 
94
88
  define do |api|
95
- api.response_template :ok do |media_type: , location: nil, headers: nil, description: nil |
89
+ api.response_template :ok do |media_type:, location: nil, headers: nil, description: nil|
96
90
  status 200
97
- description( description || 'Standard response for successful HTTP requests.' )
91
+ description(description || 'Standard response for successful HTTP requests.')
98
92
 
99
93
  media_type media_type
100
- location if location
94
+ location
101
95
  headers&.each do |(name, value)|
102
96
  header(name: name, value: value)
103
97
  end
@@ -105,16 +99,14 @@ module Praxis
105
99
 
106
100
  api.response_template :created do |media_type: nil, location: nil, headers: nil, description: nil|
107
101
  status 201
108
- description( description || 'The request has been fulfilled and resulted in a new resource being created.' )
102
+ description(description || 'The request has been fulfilled and resulted in a new resource being created.')
109
103
 
110
104
  media_type media_type if media_type
111
- location if location
105
+ location
112
106
  headers&.each do |(name, value)|
113
107
  header(name: name, value: value)
114
108
  end
115
109
  end
116
110
  end
117
-
118
111
  end
119
-
120
112
  end