reynard 0.7.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +176 -9
- data/lib/reynard/context.rb +4 -1
- data/lib/reynard/external.rb +6 -2
- data/lib/reynard/http/response.rb +3 -1
- data/lib/reynard/inflector.rb +30 -0
- data/lib/reynard/model.rb +33 -5
- data/lib/reynard/object_builder.rb +9 -5
- data/lib/reynard/specification.rb +4 -3
- data/lib/reynard/version.rb +1 -1
- data/lib/reynard.rb +4 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2942c304a1a9caaae88253e2bce40188b79bb8a5d25ccd93c8e9a04f7730e386
|
4
|
+
data.tar.gz: 12948419634f2926ae083ae364bd35f48a6b79b8f6308df95b80baafe061dce6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bcf669808d10dfff594861274b301ff77c99038ddea5e121b0ccd61336beb7089e6c20f4e566c9a29e5b813194f5b79d07c7c067c720b6b303de8c07e862944
|
7
|
+
data.tar.gz: 64f7877a9a9e44c77cb357ff36d2ecac691cfce668dc2ba2197f0b68a284e0127fab96c099ca3cb99c0390658466a4fcda3569a2e2479e643d73f95d06cf2a16
|
data/README.md
CHANGED
@@ -48,7 +48,7 @@ reynard.base_url(base_url)
|
|
48
48
|
|
49
49
|
## Calling endpoints
|
50
50
|
|
51
|
-
Assuming there is an operation
|
51
|
+
Assuming there is an operation with the `operationId` set to `employeeByUuid` you can perform a request as shown below. Note that `operationId` is a required property in the specs.
|
52
52
|
|
53
53
|
```ruby
|
54
54
|
response = reynard.
|
@@ -57,7 +57,7 @@ response = reynard.
|
|
57
57
|
execute
|
58
58
|
```
|
59
59
|
|
60
|
-
When an operation requires a body, you can add it as structured data.
|
60
|
+
When an operation requires a body, you can add it as structured data. It will be converted to JSON automatically.
|
61
61
|
|
62
62
|
```ruby
|
63
63
|
response = reynard.
|
@@ -66,13 +66,7 @@ response = reynard.
|
|
66
66
|
execute
|
67
67
|
```
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
```ruby
|
72
|
-
response.object.name #=> 'Sam Seven'
|
73
|
-
```
|
74
|
-
|
75
|
-
The response object shared much of its interface with `Net::HTTP::Response`.
|
69
|
+
The response object shares much of its interface with `Net::HTTP::Response`.
|
76
70
|
|
77
71
|
```ruby
|
78
72
|
response.code #=> '200'
|
@@ -82,6 +76,24 @@ response.body #=> '{"name":"Sam Seven"}'
|
|
82
76
|
response.parsed_body #=> { "name" => "Sam Seven" }
|
83
77
|
```
|
84
78
|
|
79
|
+
You can test for groups of response codes, basically matching `1xx` through `5xx`.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
response.informational?
|
83
|
+
response.success?
|
84
|
+
response.redirection?
|
85
|
+
response.client_error?
|
86
|
+
response.server_error?
|
87
|
+
```
|
88
|
+
|
89
|
+
In case the response status and content-type matches a response in the specification it will attempt to build an object using the specified schema.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
response.object.name #=> 'Sam Seven'
|
93
|
+
```
|
94
|
+
|
95
|
+
See below for more details about the object builder.
|
96
|
+
|
85
97
|
## Schema and models
|
86
98
|
|
87
99
|
Reynard has an object builder that allows you to get a value object backed by model classes based on the resource schema.
|
@@ -152,6 +164,148 @@ For example, in case of an array item it would look at `books` and singularize i
|
|
152
164
|
|
153
165
|
If you run into issues where Reynard doesn't properly build an object for a nested resource, it's probably because of a naming issue. It's advised to add a `title` property to the schema definition with a unique name in that case.
|
154
166
|
|
167
|
+
### Properties and model attributes
|
168
|
+
|
169
|
+
Reynard provides access to JSON properties on the model in a number of ways. There are some restrictions because of Ruby, so it's good to understand them.
|
170
|
+
|
171
|
+
Let's assume there is a payload for an `Author` model that looks like this:
|
172
|
+
|
173
|
+
```json
|
174
|
+
{"first_name":"Marcél","lastName":"Marcellus","1st-class":false}
|
175
|
+
```
|
176
|
+
|
177
|
+
Reynard attemps to give access to these properties as much as possible by sanitizing and normalizing them, so you can do the following:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
response.object.first_name #=> "Marcél"
|
181
|
+
response.object.last_name #=> "Marcellus"
|
182
|
+
```
|
183
|
+
|
184
|
+
But it's also possible to use the original casing for `lastName`.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
response.object.lastName #=> "Marcellus"
|
188
|
+
```
|
189
|
+
|
190
|
+
However, a method can't start with a number and can't contain dashes in Ruby so the following is not possible:
|
191
|
+
|
192
|
+
```
|
193
|
+
# Not valid Ruby syntax:
|
194
|
+
response.object.1st-class
|
195
|
+
```
|
196
|
+
|
197
|
+
There are two alternatives for accessing this property:
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
# The preferred solution for accessing raw property values is through the
|
201
|
+
# parsed JSON on the response object.
|
202
|
+
response.parsed_body["1st-class"]
|
203
|
+
# When you are processing nested models and you don't have access to the
|
204
|
+
# response object, you can choose to use the `[]` method.
|
205
|
+
response.object["1st-class"]
|
206
|
+
# Don't use `send` to access the property, this may not work in future
|
207
|
+
# versions.
|
208
|
+
response.object.send("1st-class")
|
209
|
+
```
|
210
|
+
|
211
|
+
#### Mapping properties
|
212
|
+
|
213
|
+
In case you are forced to access a property through a method, you could choose to map irregular property names to method names globally for all models:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
reynard.snake_cases({ "1st-class" => "first_class" })
|
217
|
+
```
|
218
|
+
|
219
|
+
This will allow you to access the property through the `first_class` method without changing the behavior of the rest of the object.
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
response.object.first_class #=> false
|
223
|
+
response.object["1st-class"] #=> false
|
224
|
+
```
|
225
|
+
|
226
|
+
Don't use this to map common property names that would work fine otherwise, because you could make things really confusing.
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
# Don't do this.
|
230
|
+
reynard.snake_cases({ "name" => "naem" })
|
231
|
+
```
|
232
|
+
|
233
|
+
### Optional properties
|
234
|
+
|
235
|
+
The current version of Reynard does not read or enforce the properties defined in the schema, instead it builds the response object based on the properties returned by the service. This was done deliberately to make it easier to access a server with a newer or older schema than the one used to build the Reynard instance.
|
236
|
+
|
237
|
+
In the code that means that you may have to check if you are receiving certain attributes, you can do this in a number of ways:
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
response.object.respond_to?(:name)
|
241
|
+
response.parsed_body["name"]
|
242
|
+
response.object["name"]
|
243
|
+
```
|
244
|
+
|
245
|
+
### Taking control of a model
|
246
|
+
|
247
|
+
As noted earlier there is a deterministic way in which Reynard decides on a model name. This means that you can define the model name before Reynard gets to it.
|
248
|
+
|
249
|
+
The easiest way to find out how Reynard does this, is to actually perform the operation and look at the response. Let's look at an example where Reynard creates a `Library` model:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
response.object.class #=> Reynard::Models::Library
|
253
|
+
response.parsed_body #=> {"name" => "Alexandria"}
|
254
|
+
```
|
255
|
+
|
256
|
+
One way to ensure that the response object has the required attributes is to defined a `valid?` method on it:
|
257
|
+
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
class Reynard
|
261
|
+
module Models
|
262
|
+
class Library < Reynard::Model
|
263
|
+
def valid?
|
264
|
+
(%w[name] - @attributes.keys).empty?
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
```
|
270
|
+
|
271
|
+
Next time you perform a request you can use your version of `Library`:
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
if response.object.valid?
|
275
|
+
puts "The library is valid!"
|
276
|
+
else
|
277
|
+
puts "The library is not valid :-( #{response.parsed_object.inspect}"
|
278
|
+
end
|
279
|
+
```
|
280
|
+
|
281
|
+
Another way to do this is to override the `attributes=` method.
|
282
|
+
|
283
|
+
```ruby
|
284
|
+
def attributes=(attributes)
|
285
|
+
super # call super or nested attributes and other features will break
|
286
|
+
raise_invalid unless valid?
|
287
|
+
end
|
288
|
+
|
289
|
+
private
|
290
|
+
|
291
|
+
def raise_invalid
|
292
|
+
return if valid?
|
293
|
+
|
294
|
+
raise(
|
295
|
+
ArgumentError,
|
296
|
+
"Library may not be initialized without all required attributes."
|
297
|
+
)
|
298
|
+
end
|
299
|
+
```
|
300
|
+
|
301
|
+
A third way of dealing with optional attributes is to define an accessor yourself.
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
def name
|
305
|
+
@attributes.fetch("name") { "Unnnamed library" }
|
306
|
+
end
|
307
|
+
```
|
308
|
+
|
155
309
|
## Logging
|
156
310
|
|
157
311
|
When you want to know what the Reynard client is doing you can enable logging.
|
@@ -168,6 +322,19 @@ The logging should be compatible with the Ruby on Rails logger.
|
|
168
322
|
reynard.logger(Rails.logger).execute
|
169
323
|
```
|
170
324
|
|
325
|
+
## Headers
|
326
|
+
|
327
|
+
You can add request headers at any time to a Reynard context, these are additive so you can easily have global headers for all requests and specific ones for an operation.
|
328
|
+
|
329
|
+
```ruby
|
330
|
+
reynard = reynard.headers(
|
331
|
+
{
|
332
|
+
"User-Agent" => "MyApplication/12.1.1 Reynard/#{Reynard::VERSION}",
|
333
|
+
"Accept" => "application/json"
|
334
|
+
}
|
335
|
+
)
|
336
|
+
```
|
337
|
+
|
171
338
|
## Debugging
|
172
339
|
|
173
340
|
You can turn on debug logging in `Net::HTTP` by setting the `DEBUG` environment variable. After setting this, all HTTP interaction will be written to STDERR.
|
data/lib/reynard/context.rb
CHANGED
@@ -8,8 +8,9 @@ class Reynard
|
|
8
8
|
extend Forwardable
|
9
9
|
def_delegators :@request_context, :verb, :path, :full_path, :url
|
10
10
|
|
11
|
-
def initialize(specification:, request_context: nil)
|
11
|
+
def initialize(specification:, inflector:, request_context: nil)
|
12
12
|
@specification = specification
|
13
|
+
@inflector = inflector
|
13
14
|
@request_context = request_context || build_request_context
|
14
15
|
end
|
15
16
|
|
@@ -59,6 +60,7 @@ class Reynard
|
|
59
60
|
def copy(**properties)
|
60
61
|
self.class.new(
|
61
62
|
specification: @specification,
|
63
|
+
inflector: @inflector,
|
62
64
|
request_context: @request_context.copy(**properties)
|
63
65
|
)
|
64
66
|
end
|
@@ -70,6 +72,7 @@ class Reynard
|
|
70
72
|
def build_response(http_response)
|
71
73
|
Reynard::Http::Response.new(
|
72
74
|
specification: @specification,
|
75
|
+
inflector: @inflector,
|
73
76
|
request_context: @request_context,
|
74
77
|
http_response: http_response
|
75
78
|
)
|
data/lib/reynard/external.rb
CHANGED
@@ -8,6 +8,7 @@ class Reynard
|
|
8
8
|
def initialize(path:, ref:)
|
9
9
|
@path = path
|
10
10
|
@relative_path, @anchor = ref.split('#', 2)
|
11
|
+
@filename = File.expand_path(@relative_path, @path)
|
11
12
|
end
|
12
13
|
|
13
14
|
def path
|
@@ -22,11 +23,14 @@ class Reynard
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
def filesystem_path
|
27
|
+
File.dirname(@filename)
|
28
|
+
end
|
29
|
+
|
25
30
|
private
|
26
31
|
|
27
32
|
def filename
|
28
|
-
filename
|
29
|
-
return filename if filename.start_with?(@path)
|
33
|
+
return @filename if @filename.start_with?(@path)
|
30
34
|
|
31
35
|
raise 'You are only allowed to reference files relative to the specification file.'
|
32
36
|
end
|
@@ -8,8 +8,9 @@ class Reynard
|
|
8
8
|
extend Forwardable
|
9
9
|
def_delegators :@http_response, :code, :content_type, :[], :body
|
10
10
|
|
11
|
-
def initialize(specification:, request_context:, http_response:)
|
11
|
+
def initialize(specification:, inflector:, request_context:, http_response:)
|
12
12
|
@specification = specification
|
13
|
+
@inflector = inflector
|
13
14
|
@request_context = request_context
|
14
15
|
@http_response = http_response
|
15
16
|
end
|
@@ -71,6 +72,7 @@ class Reynard
|
|
71
72
|
def build_object_with_media_type(media_type)
|
72
73
|
ObjectBuilder.new(
|
73
74
|
schema: @specification.schema(media_type.node),
|
75
|
+
inflector: @inflector,
|
74
76
|
parsed_body: parsed_body
|
75
77
|
).call
|
76
78
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Reynard
|
4
|
+
# Transforms property names so they are value Ruby identifiers or more readable to users.
|
5
|
+
class Inflector
|
6
|
+
def initialize
|
7
|
+
@snake_case = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Registers additional exceptions to the regular snake-case algorithm. Registering is additive
|
11
|
+
# so you can call this multiple times without losing previously registered exceptions.
|
12
|
+
def snake_cases(exceptions)
|
13
|
+
@snake_case.merge!(exceptions)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the string in snake-case, taking previously registered exceptions into account.
|
17
|
+
def snake_case(property)
|
18
|
+
@snake_case[property] || self.class.snake_case(property)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the string in snake-case.
|
22
|
+
def self.snake_case(property)
|
23
|
+
property
|
24
|
+
.to_s
|
25
|
+
.gsub(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { (Regexp.last_match(1) || Regexp.last_match(2)) << '_' }
|
26
|
+
.tr("'\"-", '___')
|
27
|
+
.downcase
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/reynard/model.rb
CHANGED
@@ -3,30 +3,45 @@
|
|
3
3
|
class Reynard
|
4
4
|
# Superclass for dynamic classes generated by the object builder.
|
5
5
|
class Model
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@attributes, :[]
|
8
|
+
|
6
9
|
class << self
|
7
10
|
# Holds references to the full schema for the model if available.
|
8
11
|
attr_accessor :schema
|
12
|
+
# The inflector to use on properties.
|
13
|
+
attr_writer :inflector
|
9
14
|
end
|
10
15
|
|
11
16
|
def initialize(attributes)
|
17
|
+
@attributes = {}
|
18
|
+
@snake_cases = self.class.snake_cases(attributes.keys)
|
12
19
|
self.attributes = attributes
|
13
20
|
end
|
14
21
|
|
15
22
|
def attributes=(attributes)
|
16
23
|
attributes.each do |name, value|
|
17
|
-
|
24
|
+
@attributes[name.to_s] = self.class.cast(name, value)
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
28
|
# Until we can set accessors based on the schema
|
22
29
|
def method_missing(attribute_name, *)
|
23
|
-
|
24
|
-
|
30
|
+
attribute_name = attribute_name.to_s
|
31
|
+
if @attributes.key?(attribute_name)
|
32
|
+
@attributes[attribute_name]
|
33
|
+
else
|
34
|
+
@attributes.fetch(@snake_cases.fetch(attribute_name))
|
35
|
+
end
|
36
|
+
rescue KeyError
|
25
37
|
raise NoMethodError, "undefined method `#{attribute_name}' for #{inspect}"
|
26
38
|
end
|
27
39
|
|
28
40
|
def respond_to_missing?(attribute_name, *)
|
29
|
-
|
41
|
+
attribute_name = attribute_name.to_s
|
42
|
+
return true if @attributes.key?(attribute_name)
|
43
|
+
|
44
|
+
@snake_cases.key?(attribute_name) && @attributes.key?(@snake_cases[attribute_name])
|
30
45
|
rescue NameError
|
31
46
|
false
|
32
47
|
end
|
@@ -37,7 +52,20 @@ class Reynard
|
|
37
52
|
property = schema.property_schema(name)
|
38
53
|
return value unless property
|
39
54
|
|
40
|
-
Reynard::ObjectBuilder.new(schema: property, parsed_body: value).call
|
55
|
+
Reynard::ObjectBuilder.new(schema: property, inflector: inflector, parsed_body: value).call
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.inflector
|
59
|
+
@inflector ||= Inflector.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.snake_cases(property_names)
|
63
|
+
property_names.each_with_object({}) do |property_name, snake_cases|
|
64
|
+
snake_case = inflector.snake_case(property_name)
|
65
|
+
next if snake_case == property_name
|
66
|
+
|
67
|
+
snake_cases[snake_case] = property_name
|
68
|
+
end
|
41
69
|
end
|
42
70
|
end
|
43
71
|
end
|
@@ -7,8 +7,9 @@ class Reynard
|
|
7
7
|
class ObjectBuilder
|
8
8
|
attr_reader :schema, :parsed_body
|
9
9
|
|
10
|
-
def initialize(schema:, parsed_body:, model_name: nil)
|
10
|
+
def initialize(schema:, inflector:, parsed_body:, model_name: nil)
|
11
11
|
@schema = schema
|
12
|
+
@inflector = inflector
|
12
13
|
@parsed_body = parsed_body
|
13
14
|
@model_name = model_name
|
14
15
|
end
|
@@ -21,7 +22,8 @@ class Reynard
|
|
21
22
|
return @model_class if defined?(@model_class)
|
22
23
|
|
23
24
|
@model_class =
|
24
|
-
self.class.model_class_get(model_name) ||
|
25
|
+
self.class.model_class_get(model_name) ||
|
26
|
+
self.class.model_class_set(model_name, schema, @inflector)
|
25
27
|
end
|
26
28
|
|
27
29
|
def call
|
@@ -41,11 +43,11 @@ class Reynard
|
|
41
43
|
nil
|
42
44
|
end
|
43
45
|
|
44
|
-
def self.model_class_set(model_name, schema)
|
46
|
+
def self.model_class_set(model_name, schema, inflector)
|
45
47
|
if schema.type == 'array'
|
46
48
|
array_model_class_set(model_name)
|
47
49
|
else
|
48
|
-
object_model_class_set(model_name, schema)
|
50
|
+
object_model_class_set(model_name, schema, inflector)
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -55,11 +57,12 @@ class Reynard
|
|
55
57
|
::Reynard::Models.const_set(model_name, Class.new(Array))
|
56
58
|
end
|
57
59
|
|
58
|
-
def self.object_model_class_set(model_name, schema)
|
60
|
+
def self.object_model_class_set(model_name, schema, inflector)
|
59
61
|
return Reynard::Model unless model_name
|
60
62
|
|
61
63
|
model_class = Class.new(Reynard::Model)
|
62
64
|
model_class.schema = schema
|
65
|
+
model_class.inflector = inflector
|
63
66
|
::Reynard::Models.const_set(model_name, model_class)
|
64
67
|
end
|
65
68
|
|
@@ -73,6 +76,7 @@ class Reynard
|
|
73
76
|
parsed_body.each do |item|
|
74
77
|
array << self.class.new(
|
75
78
|
schema: item_schema,
|
79
|
+
inflector: @inflector,
|
76
80
|
parsed_body: item
|
77
81
|
).call
|
78
82
|
end
|
@@ -14,7 +14,7 @@ class Reynard
|
|
14
14
|
|
15
15
|
# Digs a value out of the specification, taking $ref into account.
|
16
16
|
def dig(*path)
|
17
|
-
dig_into(@data, @data, path.dup)
|
17
|
+
dig_into(@data, @data, path.dup, File.dirname(@filename))
|
18
18
|
end
|
19
19
|
|
20
20
|
def servers
|
@@ -103,7 +103,7 @@ class Reynard
|
|
103
103
|
# rubocop:disable Metrics/AbcSize
|
104
104
|
# rubocop:disable Metrics/CyclomaticComplexity
|
105
105
|
# rubocop:disable Metrics/MethodLength
|
106
|
-
def dig_into(data, cursor, path)
|
106
|
+
def dig_into(data, cursor, path, filesystem_path)
|
107
107
|
while path.length.positive?
|
108
108
|
cursor = cursor[path.first]
|
109
109
|
return unless cursor
|
@@ -118,7 +118,8 @@ class Reynard
|
|
118
118
|
cursor = data
|
119
119
|
# References another file, with an optional anchor to an element in the data.
|
120
120
|
when %r{\A\./}
|
121
|
-
external = External.new(path:
|
121
|
+
external = External.new(path: filesystem_path, ref: cursor['$ref'])
|
122
|
+
filesystem_path = external.filesystem_path
|
122
123
|
path = external.path + path
|
123
124
|
cursor = external.data
|
124
125
|
end
|
data/lib/reynard/version.rb
CHANGED
data/lib/reynard.rb
CHANGED
@@ -13,11 +13,13 @@ class Reynard
|
|
13
13
|
extend Forwardable
|
14
14
|
def_delegators :build_context, :logger, :base_url, :operation, :headers, :params
|
15
15
|
def_delegators :@specification, :servers
|
16
|
+
def_delegators :@inflector, :snake_cases
|
16
17
|
|
17
18
|
autoload :Context, 'reynard/context'
|
18
19
|
autoload :External, 'reynard/external'
|
19
20
|
autoload :GroupedParameters, 'reynard/grouped_parameters'
|
20
21
|
autoload :Http, 'reynard/http'
|
22
|
+
autoload :Inflector, 'reynard/inflector'
|
21
23
|
autoload :Logger, 'reynard/logger'
|
22
24
|
autoload :MediaType, 'reynard/media_type'
|
23
25
|
autoload :Model, 'reynard/model'
|
@@ -34,6 +36,7 @@ class Reynard
|
|
34
36
|
|
35
37
|
def initialize(filename:)
|
36
38
|
@specification = Specification.new(filename: filename)
|
39
|
+
@inflector = Inflector.new
|
37
40
|
end
|
38
41
|
|
39
42
|
class << self
|
@@ -61,6 +64,6 @@ class Reynard
|
|
61
64
|
private
|
62
65
|
|
63
66
|
def build_context
|
64
|
-
Context.new(specification: @specification)
|
67
|
+
Context.new(specification: @specification, inflector: @inflector)
|
65
68
|
end
|
66
69
|
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.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manfred Stienstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- lib/reynard/http.rb
|
71
71
|
- lib/reynard/http/request.rb
|
72
72
|
- lib/reynard/http/response.rb
|
73
|
+
- lib/reynard/inflector.rb
|
73
74
|
- lib/reynard/media_type.rb
|
74
75
|
- lib/reynard/model.rb
|
75
76
|
- lib/reynard/models.rb
|