Skip to content

Commit

Permalink
Merge pull request #33 from Manfred/manfred-32-relative-external
Browse files Browse the repository at this point in the history
Keep track of current directory for external $ref
  • Loading branch information
Manfred authored Jul 7, 2023
2 parents 963ddfd + a27a97c commit c7bbdd1
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 7 deletions.
8 changes: 6 additions & 2 deletions lib/reynard/external.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class External
def initialize(path:, ref:)
@path = path
@relative_path, @anchor = ref.split('#', 2)
@filename = File.expand_path(@relative_path, @path)
end

def path
Expand All @@ -22,11 +23,14 @@ def data
end
end

def filesystem_path
File.dirname(@filename)
end

private

def filename
filename = File.expand_path(@relative_path, @path)
return filename if filename.start_with?(@path)
return @filename if @filename.start_with?(@path)

raise 'You are only allowed to reference files relative to the specification file.'
end
Expand Down
7 changes: 4 additions & 3 deletions lib/reynard/specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def initialize(filename:)

# Digs a value out of the specification, taking $ref into account.
def dig(*path)
dig_into(@data, @data, path.dup)
dig_into(@data, @data, path.dup, File.dirname(@filename))
end

def servers
Expand Down Expand Up @@ -103,7 +103,7 @@ def read
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength
def dig_into(data, cursor, path)
def dig_into(data, cursor, path, filesystem_path)
while path.length.positive?
cursor = cursor[path.first]
return unless cursor
Expand All @@ -118,7 +118,8 @@ def dig_into(data, cursor, path)
cursor = data
# References another file, with an optional anchor to an element in the data.
when %r{\A\./}
external = External.new(path: File.dirname(@filename), ref: cursor['$ref'])
external = External.new(path: filesystem_path, ref: cursor['$ref'])
filesystem_path = external.filesystem_path
path = external.path + path
cursor = external.data
end
Expand Down
2 changes: 2 additions & 0 deletions test/files/openapi/schemas/author.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ properties:
type: integer
name:
type: string
bio:
"$ref": "./bio.yml"
additionalProperties: false
9 changes: 9 additions & 0 deletions test/files/openapi/schemas/bio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type: object
title: Bio
description: >-
Biographical details about an author.
required: [age]
properties:
age:
type: integer
additionalProperties: false
5 changes: 4 additions & 1 deletion test/reynard/object_builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@ def setup
author = Reynard::ObjectBuilder.new(
schema: schema,
inflector: @inflector,
parsed_body: { id: 42, name: 'Jerry Writer' }
parsed_body: {
id: 42, name: 'Jerry Writer', bio: { age: 42 }
}
).call
assert_model_name('Author', author)
assert_equal 42, author.id
assert_equal 'Jerry Writer', author.name
assert_equal 42, author.bio.age
end
end

Expand Down
11 changes: 10 additions & 1 deletion test/reynard/specification_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ def setup
assert_equal 'integer', data
end

test 'digs into an external file through a reference in an external file' do
data = @specification.dig(
'paths', '/authors/{id}', 'get', 'responses', '200',
'content', 'application/json', 'schema',
'properties', 'bio', 'properties', 'age', 'type'
)
assert_equal 'integer', data
end

test 'digs into an external file with an anchor' do
data = @specification.dig(
'paths', '/authors/{id}', 'get', 'responses', 'default',
Expand All @@ -242,7 +251,7 @@ def setup
assert_equal %w[code message], data['required']
end

test 'digs into an external file through a refenence with with an anchor' do
test 'digs into an external file through a reference with with an anchor' do
data = @specification.dig(
'paths', '/authors/{id}', 'get', 'responses', 'default',
'content', 'application/json', 'schema', 'required'
Expand Down

0 comments on commit c7bbdd1

Please sign in to comment.