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
data/lib/media_types/scheme.rb
CHANGED
@@ -1,31 +1,66 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'media_types/scheme/validation_options'
|
4
|
+
require 'media_types/scheme/enumeration_context'
|
5
|
+
|
3
6
|
require 'media_types/scheme/allow_nil'
|
4
7
|
require 'media_types/scheme/attribute'
|
8
|
+
require 'media_types/scheme/enumeration_of_type'
|
5
9
|
require 'media_types/scheme/links'
|
6
10
|
require 'media_types/scheme/missing_validation'
|
7
11
|
require 'media_types/scheme/not_strict'
|
8
12
|
|
9
13
|
module MediaTypes
|
10
|
-
|
11
|
-
|
14
|
+
##
|
15
|
+
# Media Type Schemes can validate content to a media type, by itself. Used by the `validations` dsl.
|
16
|
+
#
|
17
|
+
# @see MediaTypes::Dsl
|
18
|
+
#
|
19
|
+
# @example A scheme to test against
|
20
|
+
#
|
21
|
+
# class MyMedia
|
22
|
+
# include MediaTypes::Dsl
|
23
|
+
#
|
24
|
+
# validations do
|
25
|
+
# attribute :foo do
|
26
|
+
# collection :bar, String
|
27
|
+
# end
|
28
|
+
# attribute :number, Numeric
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# MyMedia.valid?({ foo: { bar: ['test'] }, number: 42 })
|
33
|
+
# #=> true
|
34
|
+
#
|
35
|
+
class Scheme
|
12
36
|
|
13
|
-
|
14
|
-
|
37
|
+
# Base class for all validations errors
|
38
|
+
class ValidationError < ArgumentError; end
|
15
39
|
|
16
|
-
|
17
|
-
|
40
|
+
# Raised when it expected more data but there wasn't any left
|
41
|
+
class ExhaustedOutputError < ValidationError; end
|
18
42
|
|
19
|
-
|
20
|
-
|
43
|
+
# Raised when it did not expect more data, but there was more left
|
44
|
+
class StrictValidationError < ValidationError; end
|
21
45
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
46
|
+
# Raised when it expected not to be empty, but it was
|
47
|
+
class EmptyOutputError < ValidationError; end
|
48
|
+
|
49
|
+
# Raised when a value did not have the expected collection type
|
50
|
+
class CollectionTypeError < ValidationError; end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Creates a new scheme
|
54
|
+
#
|
55
|
+
# @param [TrueClass, FalseClass] allow_empty if true allows to be empty, if false raises EmptyOutputError if empty
|
56
|
+
# @param [NilClass, Class] force forces the type to be this type, if given
|
57
|
+
#
|
58
|
+
# @see MissingValidation
|
59
|
+
#
|
60
|
+
def initialize(allow_empty: false, force: nil)
|
27
61
|
self.validations = {}
|
28
62
|
self.allow_empty = allow_empty
|
63
|
+
self.force = force
|
29
64
|
|
30
65
|
validations.default = MissingValidation.new
|
31
66
|
end
|
@@ -33,12 +68,12 @@ module MediaTypes
|
|
33
68
|
##
|
34
69
|
# Checks if the +output+ is valid
|
35
70
|
#
|
36
|
-
# @param [#each] output
|
37
|
-
# @param [Hash] opts
|
38
|
-
# @option exhaustive [
|
39
|
-
# @option strict [
|
71
|
+
# @param [#each] output the output to test against
|
72
|
+
# @param [Hash] opts the options as defined below
|
73
|
+
# @option exhaustive [TrueClass, FalseClass] opts if true, raises when it expected more data but there wasn't any
|
74
|
+
# @option strict [TrueClass, FalseClass] opts if true, raised when it did not expect more data, but there was more
|
40
75
|
#
|
41
|
-
# @return [
|
76
|
+
# @return [TrueClass, FalseClass] true if valid, false otherwise
|
42
77
|
#
|
43
78
|
def valid?(output, **opts)
|
44
79
|
validate(output, **opts)
|
@@ -48,41 +83,22 @@ module MediaTypes
|
|
48
83
|
false
|
49
84
|
end
|
50
85
|
|
51
|
-
class ValidationOptions
|
52
|
-
attr_accessor :exhaustive, :strict, :backtrace
|
53
|
-
|
54
|
-
def initialize(exhaustive: true, strict: true, backtrace: [])
|
55
|
-
self.exhaustive = exhaustive
|
56
|
-
self.strict = strict
|
57
|
-
self.backtrace = backtrace
|
58
|
-
end
|
59
|
-
|
60
|
-
def with_backtrace(backtrace)
|
61
|
-
ValidationOptions.new(exhaustive: exhaustive, strict: strict, backtrace: backtrace)
|
62
|
-
end
|
63
|
-
|
64
|
-
def trace(*traces)
|
65
|
-
with_backtrace(backtrace.dup.concat(traces))
|
66
|
-
end
|
67
|
-
|
68
|
-
def exhaustive!
|
69
|
-
ValidationOptions.new(exhaustive: true, strict: strict, backtrace: backtrace)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
86
|
##
|
74
87
|
# Validates the +output+ and raises on certain validation errors
|
75
88
|
#
|
76
89
|
# @param [#each] output output to validate
|
77
|
-
# @option opts [
|
78
|
-
# @option opts [
|
90
|
+
# @option opts [TrueClass, FalseClass] exhaustive if true, the entire schema needs to be consumed
|
91
|
+
# @option opts [TrueClass, FalseClass] strict if true, no extra keys may be present in +output+
|
79
92
|
# @option opts[Array<String>] backtrace the current backtrace for error messages
|
80
93
|
#
|
81
94
|
# @raise ExhaustedOutputError
|
82
95
|
# @raise StrictValidationError
|
83
96
|
# @raise EmptyOutputError
|
97
|
+
# @raise CollectionTypeError
|
84
98
|
# @raise ValidationError
|
85
99
|
#
|
100
|
+
# @see #validate!
|
101
|
+
#
|
86
102
|
# @return [TrueClass]
|
87
103
|
#
|
88
104
|
def validate(output, options = nil, **opts)
|
@@ -93,6 +109,9 @@ module MediaTypes
|
|
93
109
|
end
|
94
110
|
end
|
95
111
|
|
112
|
+
#
|
113
|
+
# @private
|
114
|
+
#
|
96
115
|
def validate!(output, call_options, **_opts)
|
97
116
|
empty_guard!(output, call_options)
|
98
117
|
|
@@ -111,39 +130,114 @@ module MediaTypes
|
|
111
130
|
|
112
131
|
##
|
113
132
|
# Adds an attribute to the schema
|
133
|
+
# If a +block+ is given, uses that to test against instead of +type+
|
114
134
|
#
|
115
135
|
# @param key [Symbol] the attribute name
|
116
|
-
# @param
|
117
|
-
# @param
|
136
|
+
# @param opts [Hash] options to pass to Scheme or Attribute
|
137
|
+
# @param type [Class, #===, Scheme] The type of the value, can be anything that responds to #===,
|
138
|
+
# or scheme to use if no +&block+ is given. Defaults to String without a +&block+ and to Hash with a +&block+.
|
139
|
+
#
|
140
|
+
# @see Scheme::Attribute
|
141
|
+
# @see Scheme
|
118
142
|
#
|
119
143
|
# @example Add an attribute named foo, expecting a string
|
120
144
|
#
|
121
|
-
# class MyMedia
|
122
|
-
#
|
145
|
+
# class MyMedia
|
146
|
+
# include MediaTypes::Dsl
|
147
|
+
#
|
148
|
+
# validations do
|
123
149
|
# attribute :foo, String
|
124
150
|
# end
|
125
151
|
# end
|
126
152
|
#
|
153
|
+
# MyMedia.valid?({ foo: 'my-string' })
|
154
|
+
# # => true
|
155
|
+
#
|
156
|
+
# @example Add an attribute named foo, expecting nested scheme
|
157
|
+
#
|
158
|
+
# class MyMedia
|
159
|
+
# include MediaTypes::Dsl
|
160
|
+
#
|
161
|
+
# validations do
|
162
|
+
# attribute :foo do
|
163
|
+
# attribute :bar, String
|
164
|
+
# end
|
165
|
+
# end
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# MyMedia.valid?({ foo: { bar: 'my-string' }})
|
169
|
+
# # => true
|
170
|
+
#
|
127
171
|
def attribute(key, type = String, **opts, &block)
|
172
|
+
if block_given?
|
173
|
+
return collection(key, force: ::Hash, **opts, &block)
|
174
|
+
end
|
175
|
+
|
176
|
+
if type.is_a?(Scheme)
|
177
|
+
return validations[key] = type
|
178
|
+
end
|
179
|
+
|
128
180
|
validations[key] = Attribute.new(type, **opts, &block)
|
129
181
|
end
|
130
182
|
|
131
183
|
##
|
132
184
|
# Allow for any key.
|
133
|
-
# The
|
185
|
+
# The +&block+ defines the Schema for each value.
|
186
|
+
#
|
187
|
+
# @param [Scheme, NilClass] scheme scheme to use if no +&block+ is given
|
188
|
+
# @param [TrueClass, FalseClass] allow_empty if true, empty (no key/value present) is allowed
|
189
|
+
# @param [Class] force forces the validated object to have this type
|
190
|
+
#
|
191
|
+
# @see Scheme
|
134
192
|
#
|
135
|
-
# @
|
193
|
+
# @example Add a collection named foo, expecting any key with a defined value
|
136
194
|
#
|
137
|
-
|
138
|
-
|
195
|
+
# class MyMedia
|
196
|
+
# include MediaTypes::Dsl
|
197
|
+
#
|
198
|
+
# validations do
|
199
|
+
# collection :foo do
|
200
|
+
# any do
|
201
|
+
# attribute :bar, String
|
202
|
+
# end
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
# MyMedia.valid?({ foo: [{ anything: { bar: 'my-string' }, other_thing: { bar: 'other-string' } }] })
|
208
|
+
# # => true
|
209
|
+
#
|
210
|
+
def any(scheme = nil, force: ::Hash, allow_empty: false, &block)
|
211
|
+
unless block_given?
|
212
|
+
return validations.default = scheme
|
213
|
+
end
|
214
|
+
|
215
|
+
scheme = Scheme.new(allow_empty: allow_empty, force: force)
|
139
216
|
scheme.instance_exec(&block)
|
140
217
|
|
141
218
|
validations.default = scheme
|
142
219
|
end
|
143
220
|
|
144
221
|
##
|
145
|
-
# Allow for extra keys in the schema/collection
|
146
|
-
#
|
222
|
+
# Allow for extra keys in the schema/collection even when passing strict: true to #validate!
|
223
|
+
#
|
224
|
+
# @see Scheme::NotStrict
|
225
|
+
#
|
226
|
+
# @example Allow for extra keys in collection
|
227
|
+
#
|
228
|
+
# class MyMedia
|
229
|
+
# include MediaTypes::Dsl
|
230
|
+
#
|
231
|
+
# validations do
|
232
|
+
# collection :foo do
|
233
|
+
# attribute :required, String
|
234
|
+
# not_strict
|
235
|
+
# end
|
236
|
+
# end
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# MyMedia.valid?({ foo: [{ required: 'test', bar: 42 }] })
|
240
|
+
# # => true
|
147
241
|
#
|
148
242
|
def not_strict
|
149
243
|
validations.default = NotStrict.new
|
@@ -153,11 +247,56 @@ module MediaTypes
|
|
153
247
|
# Expect a collection such as an array or hash.
|
154
248
|
# The +block+ defines the Schema for each item in that collection.
|
155
249
|
#
|
156
|
-
# @param [Symbol] key
|
157
|
-
# @param [
|
250
|
+
# @param [Symbol] key key of the collection (same as #attribute)
|
251
|
+
# @param [NilClass, Scheme, Class] scheme scheme to use if no +&block+ is given, or type of each item in collection
|
252
|
+
# @param [TrueClass, FalseClass] allow_empty if true accepts 0 items in an enumerable
|
253
|
+
# @param [Class] force forces the value of this collection to be this type, defaults to Array.
|
254
|
+
#
|
255
|
+
# @see Scheme
|
256
|
+
#
|
257
|
+
# @example Collection with an array of string
|
258
|
+
#
|
259
|
+
# class MyMedia
|
260
|
+
# include MediaTypes::Dsl
|
261
|
+
#
|
262
|
+
# validations do
|
263
|
+
# collection :foo, String
|
264
|
+
# end
|
265
|
+
# end
|
266
|
+
#
|
267
|
+
# MyMedia.valid?({ collection: ['foo', 'bar'] })
|
268
|
+
# # => true
|
269
|
+
#
|
270
|
+
# @example Collection with defined scheme
|
158
271
|
#
|
159
|
-
|
160
|
-
|
272
|
+
# class MyMedia
|
273
|
+
# include MediaTypes::Dsl
|
274
|
+
#
|
275
|
+
# validations do
|
276
|
+
# collection :foo do
|
277
|
+
# attribute :required, String
|
278
|
+
# attribute :number, Numeric
|
279
|
+
# end
|
280
|
+
# end
|
281
|
+
# end
|
282
|
+
#
|
283
|
+
# MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
|
284
|
+
# # => true
|
285
|
+
#
|
286
|
+
def collection(key, scheme = nil, allow_empty: false, force: Array, &block)
|
287
|
+
unless block_given?
|
288
|
+
if scheme.is_a?(Scheme)
|
289
|
+
return validations[key] = scheme
|
290
|
+
end
|
291
|
+
|
292
|
+
return validations[key] = EnumerationOfType.new(
|
293
|
+
scheme,
|
294
|
+
enumeration_type: force,
|
295
|
+
allow_empty: allow_empty
|
296
|
+
)
|
297
|
+
end
|
298
|
+
|
299
|
+
scheme = Scheme.new(allow_empty: allow_empty, force: force)
|
161
300
|
scheme.instance_exec(&block)
|
162
301
|
|
163
302
|
validations[key] = scheme
|
@@ -166,6 +305,37 @@ module MediaTypes
|
|
166
305
|
##
|
167
306
|
# Expect a link
|
168
307
|
#
|
308
|
+
# @see Scheme::Links
|
309
|
+
#
|
310
|
+
# @example Links as defined in HAL, JSON-Links and other specs
|
311
|
+
#
|
312
|
+
# class MyMedia
|
313
|
+
# include MediaTypes::Dsl
|
314
|
+
#
|
315
|
+
# validations do
|
316
|
+
# link :_self
|
317
|
+
# link :image
|
318
|
+
# end
|
319
|
+
# end
|
320
|
+
#
|
321
|
+
# MyMedia.valid?({ _links: { self: { href: 'https://example.org/s' }, image: { href: 'https://image.org/i' }} })
|
322
|
+
# # => true
|
323
|
+
#
|
324
|
+
# @example Link with extra attributes
|
325
|
+
#
|
326
|
+
# class MyMedia
|
327
|
+
# include MediaTypes::Dsl
|
328
|
+
#
|
329
|
+
# validations do
|
330
|
+
# link :image do
|
331
|
+
# attribute :templated, TrueClass
|
332
|
+
# end
|
333
|
+
# end
|
334
|
+
# end
|
335
|
+
#
|
336
|
+
# MyMedia.valid?({ _links: { image: { href: 'https://image.org/{md5}', templated: true }} })
|
337
|
+
# # => true
|
338
|
+
#
|
169
339
|
def link(*args, **opts, &block)
|
170
340
|
validations.fetch(:_links) do
|
171
341
|
Links.new.tap do |links|
|
@@ -176,41 +346,51 @@ module MediaTypes
|
|
176
346
|
|
177
347
|
private
|
178
348
|
|
179
|
-
attr_accessor :validations, :allow_empty
|
349
|
+
attr_accessor :validations, :allow_empty, :force
|
180
350
|
|
351
|
+
##
|
352
|
+
# Checks if the output is nil or empty
|
353
|
+
#
|
354
|
+
# @private
|
355
|
+
#
|
181
356
|
def empty_guard!(output, options)
|
182
|
-
return unless
|
357
|
+
return unless MediaTypes::Object.new(output).empty?
|
183
358
|
throw(:end, true) if allow_empty
|
184
359
|
raise_empty!(backtrace: options.backtrace)
|
185
360
|
end
|
186
361
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
end
|
191
|
-
|
192
|
-
def enumerate(val)
|
193
|
-
self.key = val
|
194
|
-
self
|
195
|
-
end
|
196
|
-
|
197
|
-
attr_accessor :validations, :key
|
198
|
-
end
|
199
|
-
|
362
|
+
##
|
363
|
+
# Mimics Enumerable#all? with mandatory +&block+
|
364
|
+
#
|
200
365
|
def all?(enumerable, options, &block)
|
201
366
|
context = EnumerationContext.new(validations: validations)
|
202
367
|
|
368
|
+
if force && !(force === enumerable) # rubocop:disable Style/CaseEquality
|
369
|
+
raise_forced_type_error!(type: enumerable.class, backtrace: options.backtrace)
|
370
|
+
end
|
371
|
+
|
203
372
|
if enumerable.is_a?(Hash) || enumerable.respond_to?(:key)
|
204
373
|
return enumerable.all? do |key, value|
|
205
374
|
yield key, value, options: options, context: context.enumerate(key)
|
206
375
|
end
|
207
376
|
end
|
208
377
|
|
209
|
-
|
210
|
-
all?
|
378
|
+
without_forcing_type do
|
379
|
+
enumerable.each_with_index.all? do |array_like_element, i|
|
380
|
+
all?(array_like_element, options.trace(i), &block)
|
381
|
+
end
|
211
382
|
end
|
212
383
|
end
|
213
384
|
|
385
|
+
def raise_forced_type_error!(type:, backtrace:)
|
386
|
+
raise CollectionTypeError, format(
|
387
|
+
'Expected a %<expected>s, got a %<actual>s at %<backtrace>s',
|
388
|
+
expected: force,
|
389
|
+
actual: type,
|
390
|
+
backtrace: backtrace.join('->')
|
391
|
+
)
|
392
|
+
end
|
393
|
+
|
214
394
|
def raise_empty!(backtrace:)
|
215
395
|
raise EmptyOutputError, format('Expected output, got empty at %<backtrace>s', backtrace: backtrace.join('->'))
|
216
396
|
end
|
@@ -229,10 +409,19 @@ module MediaTypes
|
|
229
409
|
end
|
230
410
|
|
231
411
|
exhaustive_keys = keys.dup
|
412
|
+
# noinspection RubyScope
|
232
413
|
result = yield ->(key) { exhaustive_keys.delete(key) }
|
233
414
|
return result if exhaustive_keys.empty?
|
234
415
|
|
235
416
|
raise_exhausted!(missing_keys: exhaustive_keys, backtrace: options.backtrace)
|
236
417
|
end
|
418
|
+
|
419
|
+
def without_forcing_type
|
420
|
+
before_force = force
|
421
|
+
self.force = nil
|
422
|
+
result = yield
|
423
|
+
self.force = before_force
|
424
|
+
result
|
425
|
+
end
|
237
426
|
end
|
238
427
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'media_types/scheme'
|
4
|
+
|
5
|
+
module MediaTypes
|
6
|
+
##
|
7
|
+
# Takes care of registering validations for a media type. It allows for nested schemes and registers each one so it
|
8
|
+
# can be looked up at a later time.
|
9
|
+
#
|
10
|
+
# @see MediaType::Dsl
|
11
|
+
# @see Scheme
|
12
|
+
#
|
13
|
+
class Validations
|
14
|
+
|
15
|
+
##
|
16
|
+
# Creates a new stack of validations
|
17
|
+
#
|
18
|
+
# @param [Constructable] media_type a Constructable media type
|
19
|
+
# @param [Hash] registry the registry reference, or nil if top level
|
20
|
+
# @param [Scheme] scheme the current scheme or nil if top level
|
21
|
+
#
|
22
|
+
# @see MediaTypes::Dsl
|
23
|
+
# @see Constructable
|
24
|
+
# @see Scheme
|
25
|
+
#
|
26
|
+
def initialize(media_type, registry = {}, scheme = Scheme.new, &block)
|
27
|
+
self.media_type = media_type
|
28
|
+
self.registry = registry.merge!(media_type.to_s => scheme)
|
29
|
+
self.scheme = scheme
|
30
|
+
|
31
|
+
instance_exec(&block) if block_given?
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Looks up the validations for Constructable
|
36
|
+
#
|
37
|
+
# @param [String, Constructable] media_type
|
38
|
+
# @param [lambda] default the lambda if nothing can be found
|
39
|
+
# @return [Scheme] the scheme for the given +media_type+
|
40
|
+
#
|
41
|
+
def find(media_type, default = -> { Scheme::NotStrict.new })
|
42
|
+
registry.fetch(String(media_type)) { default.call }
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(method_name, *arguments, &block)
|
46
|
+
if scheme.respond_to?(method_name)
|
47
|
+
return scheme.send(method_name, *arguments, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def respond_to_missing?(method_name, include_private = false)
|
54
|
+
scheme.respond_to?(method_name) || super
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_accessor :media_type, :registry, :scheme
|
60
|
+
|
61
|
+
##
|
62
|
+
# Switches the inner block to a specific version
|
63
|
+
#
|
64
|
+
# @param [Numeric] version the version to switch to
|
65
|
+
#
|
66
|
+
def version(version, &block)
|
67
|
+
Validations.new(media_type.version(version), registry, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Switches the inner block to a specific view
|
72
|
+
#
|
73
|
+
# @param [String, Symbol] view the view to switch to
|
74
|
+
#
|
75
|
+
def view(view, &block)
|
76
|
+
Validations.new(media_type.view(view), registry, &block)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/media_types/version.rb
CHANGED
data/lib/media_types.rb
CHANGED
@@ -1,64 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'delegate'
|
4
|
+
|
3
5
|
require 'media_types/version'
|
4
|
-
require 'media_types/
|
6
|
+
require 'media_types/hash'
|
7
|
+
require 'media_types/object'
|
5
8
|
require 'media_types/scheme'
|
6
|
-
|
7
|
-
require 'delegate'
|
9
|
+
require 'media_types/dsl'
|
8
10
|
|
9
11
|
module MediaTypes
|
12
|
+
# Shortcut used by #collection to #view('collection')
|
10
13
|
COLLECTION_VIEW = 'collection'
|
14
|
+
|
15
|
+
# Shortcut used by #index to #view('index')
|
11
16
|
INDEX_VIEW = 'index'
|
17
|
+
|
18
|
+
# Shortcut used by #create to #view('create')
|
12
19
|
CREATE_VIEW = 'create'
|
13
20
|
|
14
21
|
module_function
|
15
22
|
|
16
|
-
|
23
|
+
##
|
24
|
+
# Called when Registerar#register is called
|
25
|
+
# @param [Registerable] registerable
|
26
|
+
def register(registerable)
|
17
27
|
require 'action_dispatch/http/mime_type'
|
18
|
-
Mime::Type.register(mime_type, symbol, synonyms)
|
19
|
-
end
|
20
|
-
|
21
|
-
class Object < SimpleDelegator
|
22
|
-
def class
|
23
|
-
__getobj__.class
|
24
|
-
end
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
mime_type = registerable.to_s
|
30
|
+
symbol = registerable.to_sym
|
31
|
+
synonyms = registerable.aliases
|
29
32
|
|
30
|
-
|
31
|
-
if __getobj__.respond_to?(:blank?)
|
32
|
-
return __getobj__.blank?
|
33
|
-
end
|
34
|
-
|
35
|
-
# noinspection RubySimplifyBooleanInspection
|
36
|
-
__getobj__.respond_to?(:empty?) ? !!__getobj__.empty? : !__getobj__ # rubocop:disable Style/DoubleNegation
|
37
|
-
end
|
38
|
-
|
39
|
-
def present?
|
40
|
-
!blank?
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class Hash < SimpleDelegator
|
45
|
-
def class
|
46
|
-
__getobj__.class
|
47
|
-
end
|
48
|
-
|
49
|
-
def ===(other)
|
50
|
-
__getobj__ === other # rubocop:disable Style/CaseEquality
|
51
|
-
end
|
52
|
-
|
53
|
-
def slice(*keep_keys)
|
54
|
-
if __getobj__.respond_to?(:slice)
|
55
|
-
return __getobj__.slice(*keep_keys)
|
56
|
-
end
|
57
|
-
|
58
|
-
h = {}
|
59
|
-
keep_keys.each { |key| h[key] = fetch(key) if key?(key) }
|
60
|
-
h
|
61
|
-
end
|
33
|
+
Mime::Type.register(mime_type, symbol, synonyms)
|
62
34
|
end
|
63
35
|
end
|
64
36
|
|
data/media_types.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
+
spec.add_development_dependency 'awesome_print'
|
26
27
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
27
28
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
28
29
|
spec.add_development_dependency 'minitest-ci'
|