Skip to content

Commit

Permalink
feat: ensure apia objects can be declared as nullable
Browse files Browse the repository at this point in the history
In Apia we can declare nullable fields like this:

class DiskTemplate < Apia::Object
  field :description, :string, null: true
  field :latest_version, Objects::DiskTemplateVersion, null: true
end

These are now declared as nullable in the spec.

closes: #55
  • Loading branch information
paulsturgess committed Jan 23, 2024
1 parent e8f2032 commit c034158
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 12 deletions.
4 changes: 2 additions & 2 deletions examples/core_api/objects/time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Time < Apia::Object
backend { |t| t.to_s }
end

field :year, type: Objects::Year do
field :year, type: Objects::Year, null: true do
backend { |t| t.year }
end

Expand All @@ -46,7 +46,7 @@ class Time < Apia::Object
backend { |t| Base64.encode64(t.to_s) }
end

field :as_date, type: :date do
field :as_date, type: :date, null: true do
backend { |t| t.strftime("%Y-%m-%d") }
end

Expand Down
13 changes: 10 additions & 3 deletions lib/apia/open_api/objects/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def initialize(spec:, definition:, schema:, id:, endpoint: nil, path: nil)
@definition = definition
@schema = schema
@id = id
@endpoint = endpoint
@endpoint = endpoint # endpoint gets specified when we are dealing with a partial response
@path = path
@children = []
end
Expand Down Expand Up @@ -130,6 +130,10 @@ def generate_schema_for_child(schema, child, all_properties_included)
schema[:properties][child.name.to_s] = generate_scalar_schema(child)
end

if child.try(:null?)
schema[:properties][child.name.to_s][:nullable] = true
end

if child.try(:required?)
schema[:required] ||= []
schema[:required] << child.name.to_s
Expand All @@ -141,21 +145,24 @@ def generate_properties_for_object(schema, child, all_properties_included)
schema[:type] = "object"
schema[:properties] ||= {}
if all_properties_included
schema[:properties][child.name.to_s] = generate_schema_ref(child)
ref = generate_schema_ref(child)
else
child_path = @path.nil? ? nil : @path + [child]

# Nested partial fields in the response have the potential to generate
# very long IDs, so we truncate them to avoid hitting the 100 character
# filename limit imposed by the rubygems gem builder.
truncated_id = @id.match(/^(.*?)\d*?(Response|Part).*$/)[1]
schema[:properties][child.name.to_s] = generate_schema_ref(
ref = generate_schema_ref(
child,
id: "#{truncated_id}Part_#{child.name}".camelize,
endpoint: @endpoint,
path: child_path
)
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] }
end

end
Expand Down
43 changes: 36 additions & 7 deletions spec/support/fixtures/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -788,12 +788,21 @@
"type": "integer"
},
"year": {
"$ref": "#/components/schemas/PostExampleFormatMultiplePartYear"
"allOf": [
{
"$ref": "#/components/schemas/PostExampleFormatMultiplePartYear"
}
],
"nullable": true
},
"as_array_of_objects": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PostExampleFormatMultiplePartAsArrayOfObjects"
"allOf": [
{
"$ref": "#/components/schemas/PostExampleFormatMultiplePartAsArrayOfObjects"
}
]
}
}
}
Expand Down Expand Up @@ -827,7 +836,12 @@
"type": "string"
},
"year": {
"$ref": "#/components/schemas/Year"
"allOf": [
{
"$ref": "#/components/schemas/Year"
}
],
"nullable": true
},
"month": {
"$ref": "#/components/schemas/MonthPolymorph"
Expand All @@ -841,7 +855,11 @@
"as_array_of_objects": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Year"
"allOf": [
{
"$ref": "#/components/schemas/Year"
}
]
}
},
"as_decimal": {
Expand All @@ -853,7 +871,8 @@
},
"as_date": {
"type": "string",
"format": "date"
"format": "date",
"nullable": true
}
}
},
Expand Down Expand Up @@ -961,7 +980,12 @@
"$ref": "#/components/schemas/Day"
},
"year": {
"$ref": "#/components/schemas/GetTestObjectPartYear"
"allOf": [
{
"$ref": "#/components/schemas/GetTestObjectPartYear"
}
],
"nullable": true
}
}
},
Expand Down Expand Up @@ -1121,7 +1145,12 @@
"$ref": "#/components/schemas/Day"
},
"year": {
"$ref": "#/components/schemas/PostTestObjectPartYear"
"allOf": [
{
"$ref": "#/components/schemas/PostTestObjectPartYear"
}
],
"nullable": true
}
}
},
Expand Down

0 comments on commit c034158

Please # to comment.