media_types 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/Gemfile.lock +3 -1
- data/README.md +228 -31
- data/Rakefile +8 -6
- data/lib/media_types/{constructable_mime_type.rb → constructable.rb} +9 -4
- data/lib/media_types/defaults.rb +31 -0
- data/lib/media_types/dsl.rb +65 -0
- data/lib/media_types/hash.rb +21 -0
- data/lib/media_types/minitest/assert_media_types_registered.rb +4 -4
- data/lib/media_types/object.rb +35 -0
- data/lib/media_types/registrar.rb +148 -0
- data/lib/media_types/scheme/allow_nil.rb +8 -1
- data/lib/media_types/scheme/any_of.rb +25 -0
- data/lib/media_types/scheme/attribute.rb +10 -0
- data/lib/media_types/scheme/enumeration_context.rb +16 -0
- data/lib/media_types/scheme/enumeration_of_type.rb +70 -0
- data/lib/media_types/scheme/validation_options.rb +27 -0
- data/lib/media_types/scheme.rb +262 -73
- data/lib/media_types/validations.rb +79 -0
- data/lib/media_types/version.rb +1 -1
- data/lib/media_types.rb +18 -46
- data/media_types.gemspec +1 -0
- metadata +28 -5
- data/lib/media_types/base/collector.rb +0 -44
- data/lib/media_types/base.rb +0 -193
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3399faaeae9e47d89ee2efe7a327dd8b1ceae7ae
|
4
|
+
data.tar.gz: 2519f99721a48e5aa5f7cf7b014e821717276d8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55f29a6d81758d3c0fa71153e63677d35d138b22e64afae8ae4e76b349219915f0e826a86d51f83c51c0ff573555abbaa807669766f413f6297ee12a9609ae4c
|
7
|
+
data.tar.gz: c4017a0fc061f4ecbde0f66a3274e59982f6e608847e4654e431f3c3644464481da56c0bd5364c88525d7da1e2f6ea45bb0a69534e37abc86340992ef29f674a
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# 0.2.0
|
2
|
+
|
3
|
+
Breaking changes to update public API and usage
|
4
|
+
|
5
|
+
- Remove `Base` class (use `MediaTypes::Dsl` instead)
|
6
|
+
- Remove a lot of configuration options as they are deemed unneeded
|
7
|
+
- Remove `active_support` dependency
|
8
|
+
- Rename `ConstructableMimeType` to `Constructable`
|
9
|
+
- Moved global scheme types to `Scheme` as subtype
|
10
|
+
- Add `MediaTypes::Dsl`
|
11
|
+
- Add `validations` block to capture schemes
|
12
|
+
- Add `registrations` block to capture register intent
|
13
|
+
- Add `defaults` block to capture mime type defaults
|
14
|
+
- Add `MediaTypes.register` class method to call `Mime::Type.register`
|
15
|
+
- Add `Registerable` capture class
|
16
|
+
- Add type / base setting for `Constructable`
|
17
|
+
- Add versioned validations
|
18
|
+
- Add forced types of `collection`s
|
19
|
+
- Add `attribute` with block
|
20
|
+
- Add `EnumerationOfType` for schema typed arrays
|
21
|
+
- Add `AnyOf` for scheme enum types
|
22
|
+
- Add non-block calls for `Scheme` dsl
|
23
|
+
- Add yard documentation to `/docs`
|
24
|
+
|
25
|
+
# 0.1.0
|
26
|
+
|
27
|
+
:baby: initial release
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
media_types (0.
|
4
|
+
media_types (0.2.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ansi (1.5.0)
|
10
|
+
awesome_print (1.8.0)
|
10
11
|
builder (3.2.3)
|
11
12
|
docile (1.3.1)
|
12
13
|
json (2.1.0)
|
@@ -30,6 +31,7 @@ PLATFORMS
|
|
30
31
|
x64-mingw32
|
31
32
|
|
32
33
|
DEPENDENCIES
|
34
|
+
awesome_print
|
33
35
|
bundler (~> 1.16)
|
34
36
|
media_types!
|
35
37
|
minitest (~> 5.0)
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
By default there are no media types registered or defined, except for an abstract base type.
|
26
26
|
|
27
|
-
|
27
|
+
## Definition
|
28
28
|
You can define media types by inheriting from this base type, or create your own base type with a class method
|
29
29
|
`.base_format` that is used to create the final media type string by injecting formatted parameters:
|
30
30
|
|
@@ -37,9 +37,9 @@ You can define media types by inheriting from this base type, or create your own
|
|
37
37
|
require 'media_types'
|
38
38
|
|
39
39
|
class Venue < MediaTypes::Base
|
40
|
-
media_type 'venue', suffix: :json,
|
40
|
+
media_type 'venue', defaults: { suffix: :json, version: 2 }
|
41
41
|
|
42
|
-
|
42
|
+
validations do
|
43
43
|
attribute :name, String
|
44
44
|
collection :location do
|
45
45
|
attribute :latitude, Numeric
|
@@ -49,22 +49,41 @@ class Venue < MediaTypes::Base
|
|
49
49
|
|
50
50
|
link :self
|
51
51
|
link :route, allow_nil: true
|
52
|
-
|
53
|
-
|
54
|
-
register_types :venue_json do
|
55
|
-
create :create_venue_json
|
56
|
-
index :venue_urls_json
|
57
|
-
collection :venue_collection_json
|
58
|
-
end
|
59
|
-
|
60
|
-
register_additional_versions do
|
52
|
+
|
61
53
|
version 1 do
|
62
54
|
attribute :name, String
|
63
55
|
attribute :coords, String
|
64
56
|
attribute :updated_at, String
|
65
|
-
|
57
|
+
|
66
58
|
link :self
|
67
59
|
end
|
60
|
+
|
61
|
+
view 'create' do
|
62
|
+
collection :location do
|
63
|
+
attribute :latitude, Numeric
|
64
|
+
attribute :longitude, Numeric
|
65
|
+
attribute :altitude, AllowNil(Numeric)
|
66
|
+
end
|
67
|
+
|
68
|
+
version 1 do
|
69
|
+
collection :location do
|
70
|
+
attribute :latitude, Numeric
|
71
|
+
attribute :longitude, Numeric
|
72
|
+
attribute :altitude, AllowNil(Numeric)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
registrations :venue_json do
|
79
|
+
view 'create', :create_venue
|
80
|
+
view 'index', :venue_urls
|
81
|
+
view 'collection', :venue_collection
|
82
|
+
|
83
|
+
versions [1,2]
|
84
|
+
|
85
|
+
suffix :json
|
86
|
+
suffix :xml
|
68
87
|
end
|
69
88
|
|
70
89
|
def self.base_format
|
@@ -73,26 +92,201 @@ class Venue < MediaTypes::Base
|
|
73
92
|
end
|
74
93
|
```
|
75
94
|
|
76
|
-
|
95
|
+
## Schema Definitions
|
77
96
|
|
78
97
|
If you define a scheme using `current_scheme { }`, you may use any of the following dsl:
|
79
98
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
99
|
+
### `attribute`
|
100
|
+
|
101
|
+
Adds an attribute to the schema, if a +block+ is given, uses that to test against instead of +type+
|
102
|
+
|
103
|
+
| param | type | description |
|
104
|
+
|-------|------|-------------|
|
105
|
+
| key | `Symbol` | the attribute name |
|
106
|
+
| opts | `Hash` | options to pass to `Scheme` or `Attribute` |
|
107
|
+
| type | `Class`, `===`, Scheme | The type of the value, can be anything that responds to `===`, or scheme to use if no `&block` is given. Defaults to `String` without a `&block` and to Hash with a `&block`. |
|
108
|
+
| &block | `Block` | defines the scheme of the value of this attribute |
|
109
|
+
|
110
|
+
#### Add an attribute named foo, expecting a string
|
111
|
+
```Ruby
|
112
|
+
require 'media_types'
|
113
|
+
|
114
|
+
class MyMedia
|
115
|
+
include MediaTypes::Dsl
|
116
|
+
|
117
|
+
validations do
|
118
|
+
attribute :foo, String
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
MyMedia.valid?({ foo: 'my-string' })
|
123
|
+
# => true
|
124
|
+
```
|
125
|
+
|
126
|
+
#### Add an attribute named foo, expecting nested scheme
|
88
127
|
|
89
|
-
|
90
|
-
|
128
|
+
```Ruby
|
129
|
+
class MyMedia
|
130
|
+
include MediaTypes::Dsl
|
131
|
+
|
132
|
+
validations do
|
133
|
+
attribute :foo do
|
134
|
+
attribute :bar, String
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
MyMedia.valid?({ foo: { bar: 'my-string' }})
|
140
|
+
# => true
|
141
|
+
```
|
91
142
|
|
92
|
-
|
143
|
+
### `any`
|
144
|
+
Allow for any key. The `&block` defines the Schema for each value.
|
93
145
|
|
94
|
-
|
95
|
-
|
146
|
+
| param | type | description |
|
147
|
+
|-------|------|-------------|
|
148
|
+
| scheme | `Scheme`, `NilClass` | scheme to use if no `&block` is given |
|
149
|
+
| allow_empty: | `TrueClass`, `FalsClass` | if true, empty (no key/value present) is allowed |
|
150
|
+
| force: | `Class`, | forces the validated value to have this type, defaults to `Hash` |
|
151
|
+
| &block | `Block` | defines the scheme of the value of this attribute |
|
152
|
+
|
153
|
+
#### Add a collection named foo, expecting any key with a defined value
|
154
|
+
```Ruby
|
155
|
+
class MyMedia
|
156
|
+
include MediaTypes::Dsl
|
157
|
+
|
158
|
+
validations do
|
159
|
+
collection :foo do
|
160
|
+
any do
|
161
|
+
attribute :bar, String
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
MyMedia.valid?({ foo: [{ anything: { bar: 'my-string' }, other_thing: { bar: 'other-string' } }] })
|
168
|
+
# => true
|
169
|
+
````
|
170
|
+
|
171
|
+
### `not_strict`
|
172
|
+
Allow for extra keys in the schema/collection even when passing `strict: true` to `#validate!`
|
173
|
+
|
174
|
+
#### Allow for extra keys in collection
|
175
|
+
|
176
|
+
```Ruby
|
177
|
+
class MyMedia
|
178
|
+
include MediaTypes::Dsl
|
179
|
+
|
180
|
+
validations do
|
181
|
+
collection :foo do
|
182
|
+
attribute :required, String
|
183
|
+
not_strict
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
MyMedia.valid?({ foo: [{ required: 'test', bar: 42 }] })
|
189
|
+
# => true
|
190
|
+
```
|
191
|
+
|
192
|
+
### `collection`
|
193
|
+
Expect a collection such as an array or hash. The `&block` defines the Schema for each item in that collection.
|
194
|
+
|
195
|
+
| param | type | description |
|
196
|
+
|-------|------|-------------|
|
197
|
+
| key | `Symbol` | key of the collection (same as `#attribute`) |
|
198
|
+
| scheme | `Scheme`, `NilClass`, `Class` | scheme to use if no `&block` is given or `Class` of each item in the |
|
199
|
+
| allow_empty: | `TrueClass`, `FalsClass` | if true, empty (no key/value present) is allowed |
|
200
|
+
| force: | `Class`, | forces the validated value to have this type, defaults to `Array` |
|
201
|
+
| &block | `Block` | defines the scheme of the value of this attribute |
|
202
|
+
|
203
|
+
|
204
|
+
#### Collection with an array of string
|
205
|
+
```Ruby
|
206
|
+
class MyMedia
|
207
|
+
include MediaTypes::Dsl
|
208
|
+
|
209
|
+
validations do
|
210
|
+
collection :foo, String
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
MyMedia.valid?({ collection: ['foo', 'bar'] })
|
215
|
+
# => true
|
216
|
+
```
|
217
|
+
|
218
|
+
#### Collection with defined scheme
|
219
|
+
|
220
|
+
```Ruby
|
221
|
+
class MyMedia
|
222
|
+
include MediaTypes::Dsl
|
223
|
+
|
224
|
+
validations do
|
225
|
+
collection :foo do
|
226
|
+
attribute :required, String
|
227
|
+
attribute :number, Numeric
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
|
233
|
+
# => true
|
234
|
+
```
|
235
|
+
|
236
|
+
### `link`
|
237
|
+
|
238
|
+
Expect a link
|
239
|
+
|
240
|
+
#### Links as defined in HAL, JSON-Links and other specs
|
241
|
+
```Ruby
|
242
|
+
class MyMedia
|
243
|
+
include MediaTypes::Dsl
|
244
|
+
|
245
|
+
validations do
|
246
|
+
link :_self
|
247
|
+
link :image
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
MyMedia.valid?({ _links: { self: { href: 'https://example.org/s' }, image: { href: 'https://image.org/i' }} })
|
252
|
+
# => true
|
253
|
+
```
|
254
|
+
|
255
|
+
|
256
|
+
#### Link with extra attributes
|
257
|
+
```Ruby
|
258
|
+
class MyMedia
|
259
|
+
include MediaTypes::Dsl
|
260
|
+
|
261
|
+
validations do
|
262
|
+
link :image do
|
263
|
+
attribute :templated, TrueClass
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
MyMedia.valid?({ _links: { self: { href: 'https://example.org/s' }, image: { href: 'https://image.org/i' }} })
|
269
|
+
# => true
|
270
|
+
```
|
271
|
+
|
272
|
+
#### Link with extra attributes
|
273
|
+
```Ruby
|
274
|
+
class MyMedia
|
275
|
+
include MediaTypes::Dsl
|
276
|
+
|
277
|
+
validations do
|
278
|
+
link :image do
|
279
|
+
attribute :templated, TrueClass
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
MyMedia.valid?({ _links: { image: { href: 'https://image.org/{md5}', templated: true }} })
|
285
|
+
# => true
|
286
|
+
```
|
287
|
+
|
288
|
+
## Validation
|
289
|
+
If your type has a validations, you can now use this media type for validation:
|
96
290
|
|
97
291
|
```Ruby
|
98
292
|
Venue.valid?({ ... })
|
@@ -102,11 +296,10 @@ Venue.validate!({ ... })
|
|
102
296
|
# => raises if it's not valid
|
103
297
|
```
|
104
298
|
|
105
|
-
|
299
|
+
## Formatting for headers
|
106
300
|
Any media type object can be coerced in valid string to be used with `Content-Type` or `Accept`:
|
107
301
|
|
108
302
|
```Ruby
|
109
|
-
|
110
303
|
Venue.mime_type.to_s
|
111
304
|
# => "application/vnd.mydomain.venue.v2+json"
|
112
305
|
|
@@ -126,7 +319,11 @@ Venue.mime_type.view('active').to_s
|
|
126
319
|
# => "application/vnd.mydomain.venue.v2.active+json"
|
127
320
|
```
|
128
321
|
|
129
|
-
|
322
|
+
## Register in Rails or Rack
|
323
|
+
Define a `registrations` block on your media type, indicating the symbol for the base type (`registrations :symbol do`)
|
324
|
+
and inside use the registrations dsl to define which media types to register. `versions array_of_numbers` determines which versions,
|
325
|
+
`suffix name` adds a suffix, `type_alias name` adds an alias and `view name, symbol` adds a view.
|
326
|
+
|
130
327
|
As long as `action_dispatch` is available, you can register the mime type with `action_dispatch/http/mime_type`:
|
131
328
|
```Ruby
|
132
329
|
Venue.register
|
@@ -147,4 +344,4 @@ push the `.gem` file to rubygems.org.
|
|
147
344
|
|
148
345
|
## Contributing
|
149
346
|
|
150
|
-
Bug reports and pull requests are welcome on GitHub at [SleeplessByte/
|
347
|
+
Bug reports and pull requests are welcome on GitHub at [SleeplessByte/media-types-ruby](https://github.com/SleeplessByte/media-types-ruby)
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
3
5
|
|
4
6
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
7
|
-
t.test_files = FileList[
|
7
|
+
t.libs << 'test'
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
12
|
+
task default: :test
|
@@ -4,26 +4,31 @@ require 'delegate'
|
|
4
4
|
require 'singleton'
|
5
5
|
|
6
6
|
module MediaTypes
|
7
|
-
class
|
7
|
+
class Constructable < SimpleDelegator
|
8
8
|
|
9
9
|
def initialize(klazz, **opts)
|
10
10
|
super klazz
|
11
11
|
self.opts = opts
|
12
12
|
end
|
13
13
|
|
14
|
+
def type(name = NO_ARG)
|
15
|
+
return opts[:type] if name == NO_ARG
|
16
|
+
Constructable.new(__getobj__, **with(type: name))
|
17
|
+
end
|
18
|
+
|
14
19
|
def version(version = NO_ARG)
|
15
20
|
return opts[:version] if version == NO_ARG
|
16
|
-
|
21
|
+
Constructable.new(__getobj__, **with(version: version))
|
17
22
|
end
|
18
23
|
|
19
24
|
def view(view = NO_ARG)
|
20
25
|
return opts[:view] if view == NO_ARG
|
21
|
-
|
26
|
+
Constructable.new(__getobj__, **with(view: view))
|
22
27
|
end
|
23
28
|
|
24
29
|
def suffix(suffix = NO_ARG)
|
25
30
|
return opts[:suffix] if suffix == NO_ARG
|
26
|
-
|
31
|
+
Constructable.new(__getobj__, **with(suffix: suffix))
|
27
32
|
end
|
28
33
|
|
29
34
|
def collection
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MediaTypes
|
4
|
+
class Defaults
|
5
|
+
def initialize(media_type, &block)
|
6
|
+
self.media_type = media_type
|
7
|
+
|
8
|
+
instance_exec(&block) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method_name, *arguments, &block)
|
12
|
+
if media_type.respond_to?(method_name)
|
13
|
+
return self.media_type = media_type.send(method_name, *arguments, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to_missing?(method_name, include_private = false)
|
20
|
+
media_type.respond_to?(method_name) || super
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_constructable
|
24
|
+
media_type
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_accessor :media_type
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'media_types/constructable'
|
4
|
+
require 'media_types/defaults'
|
5
|
+
require 'media_types/registrar'
|
6
|
+
require 'media_types/validations'
|
7
|
+
|
8
|
+
module MediaTypes
|
9
|
+
module Dsl
|
10
|
+
def self.included(base)
|
11
|
+
base.extend ClassMethods
|
12
|
+
base.class_eval do
|
13
|
+
class << self
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_accessor :media_type_constructable, :symbol_base, :media_type_registrar, :media_type_validations
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
|
23
|
+
def to_constructable
|
24
|
+
media_type_constructable.dup
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?(output, media_type = to_constructable, **opts)
|
28
|
+
validations.find(String(media_type)).valid?(output, backtrace: ['.'], **opts)
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate!(output, media_type = to_constructable, **opts)
|
32
|
+
validations.find(String(media_type)).validate(output, backtrace: ['.'], **opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
def register
|
36
|
+
registrations.to_a.map do |registerable|
|
37
|
+
MediaTypes.register(registerable)
|
38
|
+
registerable
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def media_type(name, defaults: {})
|
45
|
+
self.media_type_constructable =
|
46
|
+
Constructable.new(self, format: base_format, type: name)
|
47
|
+
.version(defaults.fetch(:version) { nil })
|
48
|
+
.suffix(defaults.fetch(:suffix) { nil })
|
49
|
+
.view(defaults.fetch(:view) { nil })
|
50
|
+
end
|
51
|
+
|
52
|
+
def defaults(&block)
|
53
|
+
self.media_type_constructable = Defaults.new(to_constructable, &block).to_constructable
|
54
|
+
end
|
55
|
+
|
56
|
+
def registrations(symbol = nil, &block)
|
57
|
+
self.media_type_registrar = media_type_registrar || Registrar.new(self, symbol: symbol, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def validations(&block)
|
61
|
+
self.media_type_validations = media_type_validations || Validations.new(to_constructable, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module MediaTypes
|
2
|
+
class Hash < SimpleDelegator
|
3
|
+
def class
|
4
|
+
__getobj__.class
|
5
|
+
end
|
6
|
+
|
7
|
+
def ===(other)
|
8
|
+
__getobj__ === other # rubocop:disable Style/CaseEquality
|
9
|
+
end
|
10
|
+
|
11
|
+
def slice(*keep_keys)
|
12
|
+
if __getobj__.respond_to?(:slice)
|
13
|
+
return __getobj__.slice(*keep_keys)
|
14
|
+
end
|
15
|
+
|
16
|
+
h = {}
|
17
|
+
keep_keys.each { |key| h[key] = fetch(key) if key?(key) }
|
18
|
+
h
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -106,10 +106,10 @@ module MediaTypes
|
|
106
106
|
uncalled = expected_types_hash.dup
|
107
107
|
|
108
108
|
uncalled.length.times do
|
109
|
-
mock.expect(:call, nil) do |
|
110
|
-
type =
|
111
|
-
symbol =
|
112
|
-
synonyms =
|
109
|
+
mock.expect(:call, nil) do |registerable|
|
110
|
+
type = registerable.to_s
|
111
|
+
symbol = registerable.to_sym
|
112
|
+
synonyms = registerable.synonyms
|
113
113
|
|
114
114
|
options = uncalled.delete(type)
|
115
115
|
options && options == [symbol, synonyms] || raise(
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MediaTypes
|
4
|
+
class Object < SimpleDelegator
|
5
|
+
def class
|
6
|
+
__getobj__.class
|
7
|
+
end
|
8
|
+
|
9
|
+
def ===(other)
|
10
|
+
__getobj__ === other # rubocop:disable Style/CaseEquality
|
11
|
+
end
|
12
|
+
|
13
|
+
def blank?
|
14
|
+
if __getobj__.respond_to?(:blank?)
|
15
|
+
return __getobj__.blank?
|
16
|
+
end
|
17
|
+
|
18
|
+
if __getobj__.respond_to?(:empty?)
|
19
|
+
return __getobj__.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
if __getobj__.respond_to?(:length)
|
23
|
+
return __getobj__.length.zero?
|
24
|
+
end
|
25
|
+
|
26
|
+
!__getobj__
|
27
|
+
end
|
28
|
+
|
29
|
+
alias empty? blank?
|
30
|
+
|
31
|
+
def present?
|
32
|
+
!blank?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|