praxis 2.0.pre.4 → 2.0.pre.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rspec +0 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +31 -0
- data/Gemfile +1 -1
- data/Guardfile +2 -1
- data/Rakefile +1 -7
- data/TODO.md +28 -0
- data/lib/api_browser/package-lock.json +7110 -0
- data/lib/praxis.rb +7 -4
- data/lib/praxis/action_definition.rb +9 -16
- data/lib/praxis/api_general_info.rb +21 -0
- data/lib/praxis/application.rb +1 -2
- data/lib/praxis/bootloader_stages/routing.rb +2 -4
- data/lib/praxis/docs/generator.rb +11 -6
- data/lib/praxis/docs/open_api_generator.rb +255 -0
- data/lib/praxis/docs/openapi/info_object.rb +39 -0
- data/lib/praxis/docs/openapi/media_type_object.rb +59 -0
- data/lib/praxis/docs/openapi/operation_object.rb +40 -0
- data/lib/praxis/docs/openapi/parameter_object.rb +69 -0
- data/lib/praxis/docs/openapi/paths_object.rb +55 -0
- data/lib/praxis/docs/openapi/request_body_object.rb +51 -0
- data/lib/praxis/docs/openapi/response_object.rb +63 -0
- data/lib/praxis/docs/openapi/responses_object.rb +44 -0
- data/lib/praxis/docs/openapi/schema_object.rb +87 -0
- data/lib/praxis/docs/openapi/server_object.rb +24 -0
- data/lib/praxis/docs/openapi/tag_object.rb +21 -0
- data/lib/praxis/extensions/attribute_filtering.rb +2 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +148 -157
- data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +15 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +90 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +68 -0
- data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +58 -0
- data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +35 -0
- data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +12 -24
- data/lib/praxis/extensions/attribute_filtering/sequel_filter_query_builder.rb +3 -2
- data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +7 -9
- data/lib/praxis/extensions/field_selection/field_selector.rb +4 -0
- data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +6 -9
- data/lib/praxis/extensions/pagination.rb +130 -0
- data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +42 -0
- data/lib/praxis/extensions/pagination/header_generator.rb +70 -0
- data/lib/praxis/extensions/pagination/ordering_params.rb +238 -0
- data/lib/praxis/extensions/pagination/pagination_handler.rb +68 -0
- data/lib/praxis/extensions/pagination/pagination_params.rb +378 -0
- data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +45 -0
- data/lib/praxis/handlers/json.rb +2 -0
- data/lib/praxis/handlers/www_form.rb +5 -0
- data/lib/praxis/handlers/{xml.rb → xml-sample.rb} +6 -0
- data/lib/praxis/links.rb +4 -0
- data/lib/praxis/mapper/active_model_compat.rb +23 -5
- data/lib/praxis/mapper/resource.rb +16 -9
- data/lib/praxis/mapper/selector_generator.rb +0 -4
- data/lib/praxis/mapper/sequel_compat.rb +1 -0
- data/lib/praxis/media_type.rb +1 -56
- data/lib/praxis/multipart/part.rb +5 -2
- data/lib/praxis/plugins/mapper_plugin.rb +1 -1
- data/lib/praxis/plugins/pagination_plugin.rb +71 -0
- data/lib/praxis/resource_definition.rb +4 -12
- data/lib/praxis/response_definition.rb +1 -1
- data/lib/praxis/route.rb +2 -4
- data/lib/praxis/routing_config.rb +4 -8
- data/lib/praxis/tasks/api_docs.rb +23 -0
- data/lib/praxis/tasks/routes.rb +10 -15
- data/lib/praxis/types/media_type_common.rb +10 -0
- data/lib/praxis/types/multipart_array.rb +62 -0
- data/lib/praxis/validation_handler.rb +1 -2
- data/lib/praxis/version.rb +1 -1
- data/praxis.gemspec +4 -5
- data/spec/functional_spec.rb +9 -6
- data/spec/praxis/action_definition_spec.rb +4 -16
- data/spec/praxis/api_general_info_spec.rb +6 -6
- data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +304 -0
- data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +39 -0
- data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +140 -0
- data/spec/praxis/extensions/field_expansion_spec.rb +6 -24
- data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +15 -11
- data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +4 -3
- data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +130 -0
- data/spec/praxis/extensions/{field_selection/support → support}/spec_resources_active_model.rb +45 -2
- data/spec/praxis/extensions/{field_selection/support → support}/spec_resources_sequel.rb +0 -0
- data/spec/praxis/media_type_spec.rb +5 -129
- data/spec/praxis/request_spec.rb +3 -22
- data/spec/praxis/resource_definition_spec.rb +1 -1
- data/spec/praxis/response_definition_spec.rb +8 -9
- data/spec/praxis/route_spec.rb +2 -9
- data/spec/praxis/routing_config_spec.rb +4 -13
- data/spec/praxis/types/multipart_array_spec.rb +4 -21
- data/spec/spec_app/config/environment.rb +0 -2
- data/spec/spec_app/design/api.rb +7 -1
- data/spec/spec_app/design/media_types/instance.rb +0 -8
- data/spec/spec_app/design/media_types/volume.rb +0 -12
- data/spec/spec_app/design/resources/instances.rb +1 -2
- data/spec/spec_helper.rb +6 -0
- data/spec/support/spec_media_types.rb +0 -73
- metadata +51 -49
- data/spec/praxis/handlers/xml_spec.rb +0 -177
- data/spec/praxis/links_spec.rb +0 -68
@@ -0,0 +1,59 @@
|
|
1
|
+
module Praxis
|
2
|
+
module Docs
|
3
|
+
module OpenApi
|
4
|
+
class MediaTypeObject
|
5
|
+
attr_reader :schema, :example
|
6
|
+
def initialize(schema:, example:)
|
7
|
+
@schema = schema
|
8
|
+
@example = example
|
9
|
+
end
|
10
|
+
|
11
|
+
def dump
|
12
|
+
{
|
13
|
+
schema: schema,
|
14
|
+
example: example,
|
15
|
+
# encoding: TODO SUPPORT IT maybe be great/necessary for multipart
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Helper to create the typical content attribute for responses and request bodies
|
20
|
+
def self.create_content_attribute_helper(type: , example_payload:, example_handlers: nil)
|
21
|
+
# Will produce 1 example encoded with a given handler (and marking it with the given content type)
|
22
|
+
unless example_handlers
|
23
|
+
example_handlers = [ {'application/json' => 'json' } ]
|
24
|
+
end
|
25
|
+
# NOTE2: we should just create a $ref here unless it's an anon mediatype...
|
26
|
+
return {} if type.is_a? SimpleMediaType # NOTE: skip if it's a SimpleMediaType?? ... is that correct?
|
27
|
+
|
28
|
+
the_schema = if type.anonymous? || ! (type < Praxis::MediaType) # Avoid referencing custom/simple Types? (i.e., just MTs)
|
29
|
+
SchemaObject.new(info: type).dump_schema
|
30
|
+
else
|
31
|
+
{ '$ref': "#/components/schemas/#{type.id}" }
|
32
|
+
end
|
33
|
+
|
34
|
+
if example_payload
|
35
|
+
examples_by_content_type = {}
|
36
|
+
rendered_payload = example_payload.dump
|
37
|
+
|
38
|
+
example_handlers.each do |spec|
|
39
|
+
content_type, handler_name = spec.first
|
40
|
+
handler = Praxis::Application.instance.handlers[handler_name]
|
41
|
+
# ReDoc is not happy to display json generated outputs when served as JSON...wtf?
|
42
|
+
generated = handler.generate(rendered_payload)
|
43
|
+
final = ( handler_name == 'json') ? JSON.parse(generated) : generated
|
44
|
+
examples_by_content_type[content_type] = final
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Key string (of MT) , value MTObject
|
49
|
+
content_hash = examples_by_content_type.each_with_object({}) do |(content_type, example_hash),accum|
|
50
|
+
accum[content_type] = MediaTypeObject.new(
|
51
|
+
schema: the_schema, # Every MT will have the same exact type..oh well .. maybe a REF?
|
52
|
+
example: example_hash,
|
53
|
+
).dump
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative 'parameter_object'
|
2
|
+
require_relative 'request_body_object'
|
3
|
+
require_relative 'responses_object'
|
4
|
+
|
5
|
+
module Praxis
|
6
|
+
module Docs
|
7
|
+
module OpenApi
|
8
|
+
class OperationObject
|
9
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#operation-object
|
10
|
+
attr_reader :id, :url, :action, :tags
|
11
|
+
def initialize(id:, url:, action:, tags:)
|
12
|
+
@id = id
|
13
|
+
@url = url
|
14
|
+
@action = action
|
15
|
+
@tags = tags
|
16
|
+
end
|
17
|
+
|
18
|
+
def dump
|
19
|
+
all_parameters = ParameterObject.process_parameters(action)
|
20
|
+
all_tags = tags + action.traits
|
21
|
+
h = {
|
22
|
+
summary: action.name.to_s,
|
23
|
+
description: action.description,
|
24
|
+
#externalDocs: {}, # TODO/FIXME
|
25
|
+
operationId: id,
|
26
|
+
responses: ResponsesObject.new(responses: action.responses).dump,
|
27
|
+
# callbacks
|
28
|
+
# deprecated: false
|
29
|
+
# security: [{}]
|
30
|
+
# servers: [{}]
|
31
|
+
}
|
32
|
+
h[:tags] = all_tags.uniq unless all_tags.empty?
|
33
|
+
h[:parameters] = all_parameters unless all_parameters.empty?
|
34
|
+
h[:requestBody] = RequestBodyObject.new(attribute: action.payload ).dump if action.payload
|
35
|
+
h
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'schema_object'
|
2
|
+
|
3
|
+
module Praxis
|
4
|
+
module Docs
|
5
|
+
module OpenApi
|
6
|
+
class ParameterObject
|
7
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameter-object
|
8
|
+
attr_reader :location, :name, :is_required, :info
|
9
|
+
def initialize(location: , name:, is_required:, info:)
|
10
|
+
@location = location
|
11
|
+
@name = name
|
12
|
+
@info = info
|
13
|
+
@is_required = is_required
|
14
|
+
end
|
15
|
+
|
16
|
+
def dump
|
17
|
+
# Fixed fields
|
18
|
+
h = { name: name, in: location }
|
19
|
+
h[:description] = info.options[:description] if info.options[:description]
|
20
|
+
h[:required] = is_required if is_required
|
21
|
+
# h[:deprecated] = false
|
22
|
+
# h[:allowEmptyValue] ??? TODO: support in Praxis
|
23
|
+
|
24
|
+
# Other supported attributes
|
25
|
+
# style
|
26
|
+
# explode
|
27
|
+
# allowReserved
|
28
|
+
|
29
|
+
# Now merge the rest schema and example
|
30
|
+
# schema
|
31
|
+
# example
|
32
|
+
# examples (Example and Examples are mutually exclusive)
|
33
|
+
schema = SchemaObject.new(info: info)
|
34
|
+
h[:schema] = schema.dump_schema
|
35
|
+
# Note: we do not support the 'content' key...we always use schema
|
36
|
+
h[:example] = schema.dump_example
|
37
|
+
h
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.process_parameters( action )
|
41
|
+
output = []
|
42
|
+
# An array, with one hash per param inside
|
43
|
+
if action.headers
|
44
|
+
(action.headers.attributes||{}).each_with_object(output) do |(name, info), out|
|
45
|
+
out << ParameterObject.new( location: 'header', name: name, is_required: info.options[:required], info: info ).dump
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if action.params
|
50
|
+
route_params = \
|
51
|
+
unless action.route
|
52
|
+
warn "Warning: No routes defined for action #{action.name}"
|
53
|
+
[]
|
54
|
+
else
|
55
|
+
action.route.path.named_captures.keys.collect(&:to_sym)
|
56
|
+
end
|
57
|
+
(action.params.attributes||{}).each_with_object(output) do |(name, info), out|
|
58
|
+
in_type = route_params.include?(name) ? :path : :query
|
59
|
+
is_required = (in_type == :path ) ? true : info.options[:required]
|
60
|
+
out << ParameterObject.new( location: in_type, name: name, is_required: is_required, info: info ).dump
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
output
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'operation_object.rb'
|
2
|
+
module Praxis
|
3
|
+
module Docs
|
4
|
+
module OpenApi
|
5
|
+
class PathsObject
|
6
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#paths-object
|
7
|
+
attr_reader :resources, :paths
|
8
|
+
def initialize(resources:)
|
9
|
+
@resources = resources
|
10
|
+
# A hash with keys of paths, and values of hash
|
11
|
+
# where the subhash has verb keys and path_items as values
|
12
|
+
# {
|
13
|
+
# "/pets": {
|
14
|
+
# "get": {...},
|
15
|
+
# "post": { ...}
|
16
|
+
# "/humans": {
|
17
|
+
# "get": {...},
|
18
|
+
@paths = Hash.new {|h,k| h[k] = {} }
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def dump
|
23
|
+
resources.each do |resource|
|
24
|
+
compute_resource_paths( resource )
|
25
|
+
end
|
26
|
+
paths
|
27
|
+
end
|
28
|
+
|
29
|
+
def compute_resource_paths( resource )
|
30
|
+
id = resource.id
|
31
|
+
# fill in the paths hash with a key for each path for each action/route
|
32
|
+
resource.actions.each do |action_name, action|
|
33
|
+
params_example = action.params ? action.params.example(nil) : nil
|
34
|
+
url = ActionDefinition.url_description(route: action.route, params: action.params, params_example: params_example)
|
35
|
+
|
36
|
+
verb = url[:verb].downcase
|
37
|
+
templetized_path = OpenApiGenerator.templatize_url(url[:path])
|
38
|
+
path_entry = paths[templetized_path]
|
39
|
+
# Let's fill in verb stuff within the working hash
|
40
|
+
raise "VERB #{_verb} already defined for #{id}!?!?!" if path_entry[verb]
|
41
|
+
|
42
|
+
action_uid = "action-#{action_name}-#{id}"
|
43
|
+
# Add a tag matching the resource name (hoping all actions of a resource are grouped)
|
44
|
+
action_tags = [resource.display_name]
|
45
|
+
path_entry[verb] = OperationObject.new( id: action_uid, url: url, action: action, tags: action_tags).dump
|
46
|
+
end
|
47
|
+
# For each path, we can further annotate with
|
48
|
+
# servers
|
49
|
+
# parameters
|
50
|
+
# But we don't have that concept in praxis
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'schema_object'
|
2
|
+
|
3
|
+
module Praxis
|
4
|
+
module Docs
|
5
|
+
module OpenApi
|
6
|
+
class RequestBodyObject
|
7
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#request-body-object
|
8
|
+
attr_reader :attribute
|
9
|
+
def initialize(attribute:)
|
10
|
+
@attribute = attribute
|
11
|
+
end
|
12
|
+
|
13
|
+
def dump
|
14
|
+
h = {}
|
15
|
+
h[:description] = attribute.options[:description] if attribute.options[:description]
|
16
|
+
h[:required] = attribute.options[:required] || false
|
17
|
+
|
18
|
+
# OpenApi wants a set of bodies per MediaType/Content-Type
|
19
|
+
# For us there's really only one schema (regardless of encoding)...
|
20
|
+
# so we'll show all the supported MTs...but repeating the schema
|
21
|
+
#dumped_schema = SchemaObject.new(info: attribute).dump_schema
|
22
|
+
|
23
|
+
example_handlers = if attribute.type < Praxis::Types::MultipartArray
|
24
|
+
ident = MediaTypeIdentifier.load('multipart/form-data')
|
25
|
+
[{ident.to_s => 'plain'}] # Multipart content type, but with the plain renderer (so there's no modification)
|
26
|
+
else
|
27
|
+
# TODO: We could run it through other handlers I guess...if they're registered
|
28
|
+
[{'application/json' => 'json'}]
|
29
|
+
end
|
30
|
+
|
31
|
+
h[:content] = MediaTypeObject.create_content_attribute_helper(type: attribute.type,
|
32
|
+
example_payload: attribute.example(nil),
|
33
|
+
example_handlers: example_handlers)
|
34
|
+
# # Key string (of MT) , value MTObject
|
35
|
+
# content_hash = info[:examples].each_with_object({}) do |(handler, example_hash),accum|
|
36
|
+
# content_type = example_hash[:content_type]
|
37
|
+
# accum[content_type] = MediaTypeObject.new(
|
38
|
+
# schema: dumped_schema, # Every MT will have the same exact type..oh well
|
39
|
+
# example: info[:examples][handler][:body],
|
40
|
+
# ).dump
|
41
|
+
# end
|
42
|
+
# # TODO! Handle Multipart types! they look like arrays now in the schema...etc
|
43
|
+
# h[:content] = content_hash
|
44
|
+
h
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative 'media_type_object'
|
2
|
+
|
3
|
+
module Praxis
|
4
|
+
module Docs
|
5
|
+
module OpenApi
|
6
|
+
class ResponseObject
|
7
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#response-object
|
8
|
+
attr_reader :info
|
9
|
+
def initialize(info:)
|
10
|
+
@info = info
|
11
|
+
default_handlers = ApiDefinition.instance.info.produces
|
12
|
+
@output_handlers = Praxis::Application.instance.handlers.select do |k,v|
|
13
|
+
default_handlers.include?(k)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump_response_headers_object( headers )
|
18
|
+
headers.each_with_object({}) do |(name,data),accum|
|
19
|
+
# data is a hash with :value and :type keys
|
20
|
+
# How did we say in that must match a value in json schema again??
|
21
|
+
accum[name] = {
|
22
|
+
schema: SchemaObject.new(info: data[:type])
|
23
|
+
# allowed values: [ data[:value] ] ??? is this the right json schema way?
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def dump
|
29
|
+
data = {
|
30
|
+
description: info.description || ''
|
31
|
+
}
|
32
|
+
if headers_object = dump_response_headers_object( info.headers )
|
33
|
+
data[:headers] = headers_object
|
34
|
+
end
|
35
|
+
|
36
|
+
if info.media_type
|
37
|
+
|
38
|
+
identifier = MediaTypeIdentifier.load(info.media_type.identifier)
|
39
|
+
example_handlers = @output_handlers.each_with_object([]) do |(name, _handler), accum|
|
40
|
+
accum.push({ (identifier + name).to_s => name})
|
41
|
+
end
|
42
|
+
data[:content] = MediaTypeObject.create_content_attribute_helper(
|
43
|
+
type: info.media_type,
|
44
|
+
example_payload: info.example(nil),
|
45
|
+
example_handlers: example_handlers)
|
46
|
+
end
|
47
|
+
|
48
|
+
# if payload = info[:payload]
|
49
|
+
# body_type= payload[:id]
|
50
|
+
# raise "WAIT! response payload doesn't have an existing id for the schema!!! (do an if, and describe it if so)" unless body_type
|
51
|
+
# data[:schema] = {"$ref" => "#/definitions/#{body_type}" }
|
52
|
+
# end
|
53
|
+
|
54
|
+
|
55
|
+
# TODO: we do not support 'links'
|
56
|
+
data
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative 'response_object'
|
2
|
+
|
3
|
+
module Praxis
|
4
|
+
module Docs
|
5
|
+
module OpenApi
|
6
|
+
class ResponsesObject
|
7
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responses-object
|
8
|
+
attr_reader :responses
|
9
|
+
def initialize(responses:)
|
10
|
+
@responses = responses
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def dump
|
15
|
+
# {
|
16
|
+
# "200": {
|
17
|
+
# "description": "a pet to be returned",
|
18
|
+
# "content": {
|
19
|
+
# "application/json": {
|
20
|
+
# "schema": {
|
21
|
+
# type: :object
|
22
|
+
# }
|
23
|
+
# }
|
24
|
+
# }
|
25
|
+
# },
|
26
|
+
# "default": {
|
27
|
+
# "description": "Unexpected error",
|
28
|
+
# "content": {
|
29
|
+
# "application/json": {
|
30
|
+
# "schema": {
|
31
|
+
# type: :object
|
32
|
+
# }
|
33
|
+
# }
|
34
|
+
# }
|
35
|
+
# }
|
36
|
+
# }
|
37
|
+
responses.each_with_object({}) do |(_response_name, response_definition), hash|
|
38
|
+
hash[response_definition.status.to_s] = ResponseObject.new(info: response_definition).dump
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Praxis
|
2
|
+
module Docs
|
3
|
+
module OpenApi
|
4
|
+
class SchemaObject
|
5
|
+
# https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schema-object
|
6
|
+
attr_reader :type, :attribute
|
7
|
+
def initialize(info:)
|
8
|
+
#info could be an attribute ... or a type?
|
9
|
+
if info.is_a? Attributor::Attribute
|
10
|
+
@attribute = info
|
11
|
+
else
|
12
|
+
@type = info
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def dump_example
|
17
|
+
ex = \
|
18
|
+
if attribute
|
19
|
+
attribute.example
|
20
|
+
else
|
21
|
+
type.example
|
22
|
+
end
|
23
|
+
ex.respond_to?(:dump) ? ex.dump : ex
|
24
|
+
end
|
25
|
+
|
26
|
+
def dump_schema
|
27
|
+
if attribute
|
28
|
+
attribute.as_json_schema(shallow: true, example: nil)
|
29
|
+
else
|
30
|
+
type.as_json_schema(shallow: true, example: nil)
|
31
|
+
end
|
32
|
+
# # TODO: FIXME: return a generic object type if the passed info was weird.
|
33
|
+
# return { type: :object } unless info
|
34
|
+
|
35
|
+
# h = {
|
36
|
+
# #type: convert_family_to_json_type( info[:type] )
|
37
|
+
# type: info[:type]
|
38
|
+
# #TODO: format?
|
39
|
+
# }
|
40
|
+
# # required prop!!!??
|
41
|
+
# h[:default] = info[:default] if info[:default]
|
42
|
+
# h[:pattern] = info[:regexp] if info[:regexp]
|
43
|
+
# # TODO: there are other possible things we can do..maximum, minimum...etc
|
44
|
+
|
45
|
+
# if h[:type] == :array
|
46
|
+
# # FIXME: ... hack it for MultiPart arrays...where there's no member attr
|
47
|
+
# member_type = info[:type][:member_attribute]
|
48
|
+
# unless member_type
|
49
|
+
# member_type = { family: :hash}
|
50
|
+
# end
|
51
|
+
# h[:items] = SchemaObject.new(info: member_type ).dump_schema
|
52
|
+
# end
|
53
|
+
# h
|
54
|
+
rescue => e
|
55
|
+
puts "Error dumping schema #{e}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_family_to_json_type( praxis_type )
|
59
|
+
case praxis_type[:family].to_sym
|
60
|
+
when :string
|
61
|
+
:string
|
62
|
+
when :hash
|
63
|
+
:object
|
64
|
+
when :array #Warning! Multipart types are arrays!
|
65
|
+
:array
|
66
|
+
when :numeric
|
67
|
+
case praxis_type[:id]
|
68
|
+
when 'Attributor-Integer'
|
69
|
+
:integer
|
70
|
+
when 'Attributor-BigDecimal'
|
71
|
+
:integer
|
72
|
+
when 'Attributor-Float'
|
73
|
+
:number
|
74
|
+
end
|
75
|
+
when :temporal
|
76
|
+
:string
|
77
|
+
when :boolean
|
78
|
+
:boolean
|
79
|
+
else
|
80
|
+
raise "Unknown praxis family type: #{praxis_type[:family]}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|