Skip to content

Commit

Permalink
fix: ensure nullable is set correctly
Browse files Browse the repository at this point in the history
part of #55
  • Loading branch information
paulsturgess committed Feb 5, 2024
1 parent 2987021 commit a4aa94f
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 54 deletions.
2 changes: 1 addition & 1 deletion examples/core_api/objects/time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Time < Apia::Object
backend { |t| t }
end

field :day_of_week, type: Objects::Day do
field :day_of_week, type: Objects::Day, null: true do
backend { |t| t.strftime("%A") }
end

Expand Down
7 changes: 6 additions & 1 deletion lib/apia/open_api/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@ def generate_schema_ref(definition, id: nil, **schema_opts)
id ||= generate_id_from_definition(definition.type.klass.definition)
success = add_to_components_schemas(definition, id, **schema_opts)

# Using allOf is a workaround to allow us to set a ref as `nullable` in OpenAPI 3.0
# In OpenAPI 3.0 sibling properties are not allowed for $refs (but are allowed in 3.1)
# For simplicity we just wrap every ref in allOf
if success
{ "$ref": "#/components/schemas/#{id}" }
{
allOf: [{ "$ref": "#/components/schemas/#{id}" }]
}
else # no properties were defined, so just declare an object with unknown properties
{ type: "object" }
end
Expand Down
10 changes: 4 additions & 6 deletions lib/apia/open_api/objects/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,14 @@ def build_properties_for_polymorph(field_name, field, properties)
else
# We assume the partially selected attributes must be present in all of the polymorph options
# and that each option returns the same data type for that attribute.
# The same 'allOf workaround' is used here as for objects and enums below.
ref = generate_schema_ref(
field.type.klass.definition.options.values.first,
id: generate_field_id(field_name),
endpoint: @endpoint,
path: [field]
)

properties[field_name] = { allOf: [ref] }
properties[field_name] = ref
end
properties[field_name][:description] = field.description if field.description.present?
end
Expand Down Expand Up @@ -135,13 +134,10 @@ def build_properties_for_array(field_name, field, properties)
properties[field_name][:description] = field.description if field.description.present?
end

# Using allOf is a 'workaround' so that we can include a description for the field
# In OpenAPI 3.0 sibling properties are not allowed for $refs (but are allowed in 3.1)
# We don't want to put the description on the $ref itself because the description is
# specific to the endpoint and not necessarily applicable to all uses of the $ref.
def build_properties_for_object_or_enum(field_name, field, properties)
properties[field_name] = {}
properties[field_name][:description] = field.description if field.description.present?
if field_includes_all_properties?(field)
ref = generate_schema_ref(field)
else
Expand All @@ -152,7 +148,8 @@ def build_properties_for_object_or_enum(field_name, field, properties)
path: [field]
)
end
properties[field_name][:allOf] = [ref]
ref[:description] = field.description if field.description.present?
properties[field_name] = ref
end

def field_includes_all_properties?(field)
Expand Down Expand Up @@ -270,6 +267,7 @@ def add_to_responses_components(http_status_code, definitions, id)
oneOf: definitions.map { |d| generate_ref("schemas", http_status_code, [d]) }
}

# we don't need the ref allOf workaround here because these responses are not nullable
schema = { "$ref": "#/components/schemas/#{one_of_id}" }
end

Expand Down
3 changes: 1 addition & 2 deletions lib/apia/open_api/objects/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,7 @@ def generate_properties_for_object(schema, child, all_properties_included)
)
end

# Using allOf is a workaround to allow us to set a ref as `nullable` in OpenAPI 3.0
schema[:properties][child.name.to_s] = { allOf: [ref] }
schema[:properties][child.name.to_s] = ref
end

end
Expand Down
Loading

0 comments on commit a4aa94f

Please # to comment.