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,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
112
  unless opts.key?(:required)
128
- opts = {required: true, null: false}.merge(opts) # Make the payload required and non-nullable by default
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