reynard 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1655a999a92e83993f4fdba62a9eedc870b18ada0339278d1c899e24f087b3bc
4
- data.tar.gz: 926420c57d99767386d9aea1ef50b5bda317ea437a11dc3646bf3a5cc8a902be
3
+ metadata.gz: 73e8e17f725539aac5739311c093ac8ff851eab5c9bc3016cdd3839b29cdcc8b
4
+ data.tar.gz: a8fc3ba0731ad45a5f92324d819d84b7bf5fb418d8f4eb3751b5a7b2814b6a19
5
5
  SHA512:
6
- metadata.gz: 6c9834fae550aae2557a6833e4491eed9d426c9fdb5b6c2cf31ff5c9fe80569a00070affdfb76e9c90611400f959df5a7e377dfe906a813655e6b28bc3ced4ac
7
- data.tar.gz: a22f676bb82b37d6bceb87028aeae10a78f2fd394cdef990eea7661842d1b0a2644ac20e5188f29730c62d54ab36498b1fe7112ebc1ffe872b3f3b6dfa848aff
6
+ metadata.gz: e6b03cde95bd0bf69a03f860d3eaa57bf9d39f1deb6c9abfd719d4fdbaec728f1c8d5a2485493e5b403cdd0b57a80784c3dd48c02eef5d957eaf7638cacf91b0
7
+ data.tar.gz: f56a52f52d041ce58b69e1d799072510131a4f471560a908b24bb1e01630ef1e971d07e1b88845fae298e90e1d9f6f6dc1ad7990375c35d9c0ae357c69644a0c
data/lib/reynard.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'net/http/persistent'
3
4
  require 'forwardable'
4
5
  require 'multi_json'
5
6
  require 'rack'
@@ -32,6 +33,14 @@ class Reynard
32
33
  @specification = Specification.new(filename: filename)
33
34
  end
34
35
 
36
+ def self.http
37
+ @http ||= begin
38
+ http = Net::HTTP::Persistent.new(name: 'Reynard')
39
+ http.debug_output = $stderr if ENV['DEBUG']
40
+ http
41
+ end
42
+ end
43
+
35
44
  private
36
45
 
37
46
  def build_context
@@ -53,7 +53,7 @@ class Reynard
53
53
  media_type = @specification.media_type(
54
54
  @request_context.operation.node,
55
55
  http_response.code,
56
- http_response['Content-Type'].split(';').first
56
+ http_response.content_type
57
57
  )
58
58
  ObjectBuilder.new(
59
59
  media_type: media_type,
@@ -15,7 +15,7 @@ class Reynard
15
15
  end
16
16
 
17
17
  def perform
18
- build_http.request(build_request)
18
+ Reynard.http.request(uri, build_request)
19
19
  end
20
20
 
21
21
  private
@@ -29,12 +29,6 @@ class Reynard
29
29
  end
30
30
  end
31
31
 
32
- def build_http
33
- http = Net::HTTP.new(uri.hostname, uri.port)
34
- http.set_debug_output($stderr) if ENV['DEBUG']
35
- http
36
- end
37
-
38
32
  def build_http_get
39
33
  Net::HTTP::Get.new(uri, @request_context.headers)
40
34
  end
data/lib/reynard/model.rb CHANGED
@@ -16,10 +16,14 @@ class Reynard
16
16
  # Until we can set accessors based on the schema
17
17
  def method_missing(attribute_name, *)
18
18
  instance_variable_get("@#{attribute_name}")
19
+ rescue NameError
20
+ raise NoMethodError, "undefined method `#{attribute_name}' for #{inspect}"
19
21
  end
20
22
 
21
23
  def respond_to_missing?(attribute_name, *)
22
- !!instance_variable_get("@#{attribute_name}")
24
+ !instance_variable_get("@#{attribute_name}").nil?
25
+ rescue NameError
26
+ false
23
27
  end
24
28
  end
25
29
  end
@@ -11,28 +11,52 @@ class Reynard
11
11
  @http_response = http_response
12
12
  end
13
13
 
14
- # Object.const_set(@media_type.schema_name, Class.new(Reynard::Model))
15
14
  def object_class
16
15
  if @media_type.schema_name
17
- self.class.model_class(@media_type.schema_name)
16
+ self.class.model_class(@media_type.schema_name, @schema.object_type)
17
+ else
18
+ OpenStruct
19
+ end
20
+ end
21
+
22
+ def item_object_class
23
+ if @schema.item_schema_name
24
+ self.class.model_class(@schema.item_schema_name, 'object')
18
25
  else
19
26
  OpenStruct
20
27
  end
21
28
  end
22
29
 
23
30
  def call
24
- case @media_type.media_type
25
- when 'application/json'
26
- object_class.new(MultiJson.load(@http_response.body))
31
+ if @schema.object_type == 'array'
32
+ array = object_class.new
33
+ data.each { |attributes| array << item_object_class.new(attributes) }
34
+ array
27
35
  else
28
- FailedRequest.new
36
+ object_class.new(data)
29
37
  end
30
38
  end
31
39
 
32
- def self.model_class(name)
40
+ def data
41
+ @data ||= MultiJson.load(@http_response.body)
42
+ end
43
+
44
+ def self.model_class(name, object_type)
45
+ model_class_get(name) || model_class_set(name, object_type)
46
+ end
47
+
48
+ def self.model_class_get(name)
33
49
  Reynard::Models.const_get(name)
34
50
  rescue NameError
35
- Reynard::Models.const_set(name, Class.new(Reynard::Model))
51
+ nil
52
+ end
53
+
54
+ def self.model_class_set(name, object_type)
55
+ if object_type == 'array'
56
+ Reynard::Models.const_set(name, Class.new(Array))
57
+ else
58
+ Reynard::Models.const_set(name, Class.new(Reynard::Model))
59
+ end
36
60
  end
37
61
  end
38
62
  end
@@ -3,11 +3,12 @@
3
3
  class Reynard
4
4
  # Holds reference and object type for a schema in the API specification.
5
5
  class Schema
6
- attr_reader :node, :object_type
6
+ attr_reader :node, :object_type, :item_schema_name
7
7
 
8
- def initialize(node:, object_type:)
8
+ def initialize(node:, object_type:, item_schema_name:)
9
9
  @node = node
10
10
  @object_type = object_type
11
+ @item_schema_name = item_schema_name
11
12
  end
12
13
  end
13
14
  end
@@ -45,7 +45,7 @@ class Reynard
45
45
  def media_type(operation_node, response_code, media_type)
46
46
  responses = dig(*operation_node, 'responses')
47
47
  response_code = responses.key?(response_code) ? response_code : 'default'
48
- response = responses.dig(response_code, 'content', media_type)
48
+ response, media_type = media_type_response(responses, response_code, media_type)
49
49
  return unless response
50
50
 
51
51
  MediaType.new(
@@ -54,11 +54,29 @@ class Reynard
54
54
  )
55
55
  end
56
56
 
57
+ def media_type_response(responses, response_code, media_type)
58
+ responses.dig(response_code, 'content').each do |expression, response|
59
+ return response, expression if self.class.media_type_matches?(media_type, expression)
60
+ end
61
+ nil
62
+ end
63
+
57
64
  def schema(media_type_node)
58
65
  schema = dig(*media_type_node, 'schema')
59
66
  return unless schema
60
67
 
61
- Schema.new(node: [*media_type_node, 'schema'], object_type: schema['type'])
68
+ Schema.new(
69
+ node: [*media_type_node, 'schema'],
70
+ object_type: schema['type'],
71
+ item_schema_name: item_schema_name(schema)
72
+ )
73
+ end
74
+
75
+ def self.media_type_matches?(media_type, expression)
76
+ return true unless media_type
77
+ return true if expression == media_type
78
+
79
+ false
62
80
  end
63
81
 
64
82
  private
@@ -89,6 +107,11 @@ class Reynard
89
107
  ref&.split('/')&.last
90
108
  end
91
109
 
110
+ def item_schema_name(schema)
111
+ ref = schema.dig('items', '$ref')
112
+ ref&.split('/')&.last
113
+ end
114
+
92
115
  def object_name(_schema)
93
116
  'Book'
94
117
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Reynard
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.4'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reynard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manfred Stienstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-05 00:00:00.000000000 Z
11
+ date: 2021-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-http-persistent
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rack
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webrick
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  description: |2
84
112
  Reynard is an OpenAPI client for Ruby. It operates directly on the OpenAPI specification without
85
113
  the need to generate any source code.