media_types 0.1.3 → 0.2.0
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 +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
|