reynard 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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.