media_types 2.0.1 → 2.1.0

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: 015cccf33a3af68f0e282b1c95c7ffe7015ae4a889e8e20731a2abfcc80322f2
4
- data.tar.gz: edbdf2641d03043cadfd60392ea9b092e902a4471febf95a7bccb3e926b69e58
3
+ metadata.gz: d034c7e7a7fd3a142dd997efab0d1c3e61f2cbe3170078544f4f456c485ad4ec
4
+ data.tar.gz: 20dbb0fbdf7e9f93c79575239de5e9a4e2220dbd7d3a0fe1d41145c1b2a97b54
5
5
  SHA512:
6
- metadata.gz: 8d55fd91afc2be432ccc7842d8b53df3a6f8190d487111f49c04386b77678d5b88088406f7d40bc1535aebe48af6617edcab46141689f57759d5430e75d94db7
7
- data.tar.gz: '09f57d4eeee475e1dc40aff213128bee1b69a35b166d7e055f3a60146d77972723c2feafeae6fecb58e87910fbac8e9cafbdc1f3690940863476f90cc54f48f4'
6
+ metadata.gz: b589dbf3292df73632d3d8c98b6b73ed2dec08099b64406b4a1ca2c2cbe19b5cf7161efefc2b05c3bff634b03b6056c6a8f4770ac038e559710415bbad663e10
7
+ data.tar.gz: 2ce0c0747e94f01de399e28cd262b921912097c9bfea2d205abcb11937f116d078366ebcee8a8f0999c12cada9a7b1ce1093ad51d80d397cfc73d5cd145424f8
data/CHANGELOG.md CHANGED
@@ -1,41 +1,48 @@
1
- # 2.0.1
1
+ # Changelog
2
2
 
3
- - Views can now be accessed indifferently.
4
- - Attribute keys no longer match indifferently.
5
- - Fixed infinite loop when validating non-hash, non-array items.
3
+ ## 2.1.0
6
4
 
7
- # 2.0.0
5
+ - Add `override_suffix` to force a specific suffix
6
+ - Fix all deprecation warnings
8
7
 
9
- - Removed ability to set default suffix. All suffixes now default to `+json`.
10
- - Suffixes are now set for a given view and version instead of as a block.
11
- - Added `suffix :yoursuffix` command to override the default `:json` suffix.
12
- - Removed defaults block.
13
- - Removed registrations block.
8
+ ## 2.0.1
14
9
 
15
- # 1.0.0
10
+ - Views can now be accessed indifferently.
11
+ - Attribute keys no longer match indifferently.
12
+ - Fixed infinite loop when validating non-hash, non-array items.
16
13
 
17
- - Added the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
18
- - `media_type` has been replaced with `use_name`.
19
- - It is no longer possible to set a default version. Please use `version <x> do` instead.
20
- - You no longer need to specify a custom format string. If you set an organisation with `def self.organisation` or set a module wide organisation with `MediaTypes::set_organisation <module>, '<organisation>'` the library will generate identifiers for you.
21
- - `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
22
- - Added the `empty` validation to mark an empty object as valid.
23
- - Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
24
- - Added `version(x)` and `view(x)` functions.
25
- - Added an `available_validations` functions that returns all defined validations.
26
- - Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
27
- - Fixed an issue where undefined validations would accept an empty object.
14
+ ## 2.0.0
28
15
 
29
- # 0.6.2
16
+ - Removed ability to set default suffix. All suffixes now default to `+json`.
17
+ - Suffixes are now set for a given view and version instead of as a block.
18
+ - Added `suffix :yoursuffix` command to override the default `:json` suffix.
19
+ - Removed defaults block.
20
+ - Removed registrations block.
21
+
22
+ ## 1.0.0
23
+
24
+ - Added the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
25
+ - `media_type` has been replaced with `use_name`.
26
+ - It is no longer possible to set a default version. Please use `version <x> do` instead.
27
+ - You no longer need to specify a custom format string. If you set an organisation with `def self.organisation` or set a module wide organisation with `MediaTypes::set_organisation <module>, '<organisation>'` the library will generate identifiers for you.
28
+ - `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
29
+ - Added the `empty` validation to mark an empty object as valid.
30
+ - Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
31
+ - Added `version(x)` and `view(x)` functions.
32
+ - Added an `available_validations` functions that returns all defined validations.
33
+ - Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
34
+ - Fixed an issue where undefined validations would accept an empty object.
35
+
36
+ ## 0.6.2
30
37
 
31
38
  - Fix handling empty collections
32
39
 
33
- # 0.6.1
40
+ ## 0.6.1
34
41
 
35
42
  - Fix no `validations` error on `validatable?` (now returns `false`)
36
43
  - Update `bundler` to `2.x`
37
44
 
38
- # 0.6.0
45
+ ## 0.6.0
39
46
 
40
47
  - Change default expected type for `attribute` to Object
41
48
  - Remove default `actionpack` calls for `.register`
@@ -43,28 +50,28 @@
43
50
  - Add integration for registering with `http` (http.rb)
44
51
  - Fix stack overflow for cyclic schema
45
52
 
46
- # 0.5.5
53
+ ## 0.5.5
47
54
 
48
55
  - Fix an issue with `attribute(optional:, &block)` not passing `optional:` to the created `collection`.
49
56
 
50
- # 0.5.4
57
+ ## 0.5.4
51
58
 
52
59
  - Fix formatter reworked template when fields are not present
53
60
 
54
- # 0.5.3
61
+ ## 0.5.3
55
62
 
56
63
  - Remove `require 'awesome_print'` in library code as it's marked as a development dependency onlvy
57
64
 
58
- # 0.5.2
65
+ ## 0.5.2
59
66
 
60
67
  - Add requires in files with missing requires
61
68
 
62
- # 0.5.1
69
+ ## 0.5.1
63
70
 
64
71
  - Fix merging optional attributes
65
72
  - Change `#inspect` to look like a tree
66
73
 
67
- # 0.5.0
74
+ ## 0.5.0
68
75
 
69
76
  - Change internal representation of key to symbol
70
77
  - Change default type from `nil` to `Object`, removing special behaviour for nil
@@ -83,11 +90,11 @@
83
90
  - Raise error if `self.base_format` is not available at time of `Dsl.media_type` call
84
91
  - Fix `expected_type` guard for arrays, nil, or arrays with nil.
85
92
 
86
- # 0.4.1
93
+ ## 0.4.1
87
94
 
88
95
  - Use strings for `:_links`, matching the other validation keys
89
96
 
90
- # 0.4.0
97
+ ## 0.4.0
91
98
 
92
99
  - Simplify `assert_media_type_format` by dumping views completely
93
100
  - Add test for `merge`
@@ -95,59 +102,59 @@
95
102
  - Add test for `validatable?`
96
103
  - Add block passing to `Scheme.new`
97
104
 
98
- # 0.3.0
105
+ ## 0.3.0
99
106
 
100
107
  - Add `merge` dsl to merge two `Scheme`
101
108
 
102
- # 0.2.6
109
+ ## 0.2.6
103
110
 
104
111
  - Change validation to accept both symbolised and stringified input ánd validations
105
112
 
106
- # 0.2.5
113
+ ## 0.2.5
107
114
 
108
115
  - Add automatic require for `media_types/scheme/any_of`
109
116
 
110
- # 0.2.4
117
+ ## 0.2.4
111
118
 
112
119
  - Change messages for `assert_media_types_registered` to be more informative and consistent
113
120
 
114
- # 0.2.3
121
+ ## 0.2.3
115
122
 
116
123
  - Fix an issue with `Hash#compact` which was introduce in 2.4+. Now works with Ruby 2.3
117
124
 
118
- # 0.2.2
125
+ ## 0.2.2
119
126
 
120
127
  - Fix an issue with `Registrar#versions`
121
128
  - Fix link in the gemspec to Github
122
129
 
123
- # 0.2.1
130
+ ## 0.2.1
124
131
 
125
- - Fix an issue with `Constructable#valid?` and `Constructable#validate!`
132
+ - Fix an issue with `Constructable#valid?` and `Constructable#validate!`
126
133
 
127
- # 0.2.0
134
+ ## 0.2.0
128
135
 
129
136
  Breaking changes to update public API and usage
130
137
 
131
- - Remove `Base` class (use `MediaTypes::Dsl` instead)
132
- - Remove a lot of configuration options as they are deemed unneeded
133
- - Remove `active_support` dependency
134
- - Rename `ConstructableMimeType` to `Constructable`
135
- - Moved global scheme types to `Scheme` as subtype
136
- - Add `MediaTypes::Dsl`
137
- - Add `validations` block to capture schemes
138
- - Add `registrations` block to capture register intent
139
- - Add `defaults` block to capture mime type defaults
140
- - Add `MediaTypes.register` class method to call `Mime::Type.register`
141
- - Add `Registerable` capture class
142
- - Add type / base setting for `Constructable`
143
- - Add versioned validations
144
- - Add forced types of `collection`s
145
- - Add `attribute` with block
146
- - Add `EnumerationOfType` for schema typed arrays
147
- - Add `AnyOf` for scheme enum types
148
- - Add non-block calls for `Scheme` dsl
149
- - Add yard documentation to `/docs`
150
-
151
- # 0.1.0
138
+ - Remove `Base` class (use `MediaTypes::Dsl` instead)
139
+ - Remove a lot of configuration options as they are deemed unneeded
140
+ - Remove `active_support` dependency
141
+ - Rename `ConstructableMimeType` to `Constructable`
142
+ - Moved global scheme types to `Scheme` as subtype
143
+ - Add `MediaTypes::Dsl`
144
+ - Add `validations` block to capture schemes
145
+ - Add `registrations` block to capture register intent
146
+ - Add `defaults` block to capture mime type defaults
147
+ - Add `MediaTypes.register` class method to call `Mime::Type.register`
148
+ - Add `Registerable` capture class
149
+ - Add type / base setting for `Constructable`
150
+ - Add versioned validations
151
+ - Add forced types of `collection`s
152
+ - Add `attribute` with block
153
+ - Add `EnumerationOfType` for schema typed arrays
154
+ - Add `AnyOf` for scheme enum types
155
+ - Add non-block calls for `Scheme` dsl
156
+ - Add yard documentation to `/docs`
157
+
158
+ ## 0.1.0
152
159
 
153
160
  :baby: initial release
data/Gemfile.lock CHANGED
@@ -1,41 +1,43 @@
1
- PATH
2
- remote: .
3
- specs:
4
- media_types (2.0.1)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- ansi (1.5.0)
10
- awesome_print (1.8.0)
11
- builder (3.2.4)
12
- docile (1.3.2)
13
- minitest (5.14.0)
14
- minitest-reporters (1.4.2)
15
- ansi
16
- builder
17
- minitest (>= 5.0)
18
- ruby-progressbar
19
- oj (3.10.5)
20
- rake (13.0.1)
21
- ruby-progressbar (1.10.1)
22
- simplecov (0.18.5)
23
- docile (~> 1.1)
24
- simplecov-html (~> 0.11)
25
- simplecov-html (0.12.2)
26
-
27
- PLATFORMS
28
- ruby
29
-
30
- DEPENDENCIES
31
- awesome_print
32
- bundler (>= 1.16.1)
33
- media_types!
34
- minitest (~> 5.0)
35
- minitest-reporters
36
- oj
37
- rake (>= 12.0)
38
- simplecov
39
-
40
- BUNDLED WITH
41
- 1.17.3
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ media_types (2.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ansi (1.5.0)
10
+ awesome_print (1.9.2)
11
+ builder (3.2.4)
12
+ docile (1.4.0)
13
+ minitest (5.14.4)
14
+ minitest-reporters (1.4.3)
15
+ ansi
16
+ builder
17
+ minitest (>= 5.0)
18
+ ruby-progressbar
19
+ oj (3.13.1)
20
+ rake (13.0.6)
21
+ ruby-progressbar (1.11.0)
22
+ simplecov (0.21.2)
23
+ docile (~> 1.1)
24
+ simplecov-html (~> 0.11)
25
+ simplecov_json_formatter (~> 0.1)
26
+ simplecov-html (0.12.3)
27
+ simplecov_json_formatter (0.1.3)
28
+
29
+ PLATFORMS
30
+ x64-mingw32
31
+
32
+ DEPENDENCIES
33
+ awesome_print
34
+ bundler (>= 2)
35
+ media_types!
36
+ minitest (~> 5.0)
37
+ minitest-reporters
38
+ oj
39
+ rake (>= 12.0)
40
+ simplecov
41
+
42
+ BUNDLED WITH
43
+ 2.2.7
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Derk-Jan Karrenbeld
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/6f2dc1fb37ecb98c4363/maintainability)](https://codeclimate.com/github/SleeplessByte/media-types-ruby/maintainability)
6
6
 
7
- Media Types based on scheme, with versioning, views, suffixes and validations. Integrations available for [Rails](https://github.com/rails/rails) / ActionPack and [http.rb](https://github.com/httprb/http).
7
+ Media Types based on scheme, with versioning, views, suffixes and validations.
8
8
 
9
9
  This library makes it easy to define schemas that can be used to validate JSON objects based on their Content-Type.
10
10
 
@@ -114,13 +114,13 @@ If you include 'MediaTypes::Dsl' in your class you can use the following functio
114
114
 
115
115
  Adds an attribute to the schema, if a +block+ is given, uses that to test against instead of +type+
116
116
 
117
- | param | type | description |
118
- |-------|------|-------------|
119
- | key | `Symbol` | the attribute name |
120
- | opts | `Hash` | options to pass to `Scheme` or `Attribute` |
121
- | 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 `Object` without a `&block` and to Hash with a `&block`. |
122
- | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
123
- | &block | `Block` | defines the scheme of the value of this attribute |
117
+ | param | type | description |
118
+ | --------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
119
+ | key | `Symbol` | the attribute name |
120
+ | opts | `Hash` | options to pass to `Scheme` or `Attribute` |
121
+ | 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 `Object` without a `&block` and to Hash with a `&block`. |
122
+ | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
123
+ | &block | `Block` | defines the scheme of the value of this attribute |
124
124
 
125
125
  #### Add an attribute named foo, expecting a string
126
126
  ```Ruby
@@ -158,12 +158,12 @@ MyMedia.valid?({ foo: { bar: 'my-string' }})
158
158
  ### `any`
159
159
  Allow for any key. The `&block` defines the Schema for each value.
160
160
 
161
- | param | type | description |
162
- |-------|------|-------------|
163
- | scheme | `Scheme`, `NilClass` | scheme to use if no `&block` is given |
164
- | allow_empty: | `TrueClass`, `FalsClass` | if true, empty (no key/value present) is allowed |
165
- | expected_type: | `Class`, | forces the validated value to have this type, defaults to `Hash`. Use `Object` if either `Hash` or `Array` is fine |
166
- | &block | `Block` | defines the scheme of the value of this attribute |
161
+ | param | type | description |
162
+ | -------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
163
+ | scheme | `Scheme`, `NilClass` | scheme to use if no `&block` is given |
164
+ | allow_empty: | `TrueClass`, `FalsClass` | if true, empty (no key/value present) is allowed |
165
+ | expected_type: | `Class`, | forces the validated value to have this type, defaults to `Hash`. Use `Object` if either `Hash` or `Array` is fine |
166
+ | &block | `Block` | defines the scheme of the value of this attribute |
167
167
 
168
168
  #### Add a collection named foo, expecting any key with a defined value
169
169
  ```Ruby
@@ -207,14 +207,14 @@ MyMedia.valid?({ foo: [{ required: 'test', bar: 42 }] })
207
207
  ### `collection`
208
208
  Expect a collection such as an array or hash. The `&block` defines the Schema for each item in that collection.
209
209
 
210
- | param | type | description |
211
- |-------|------|-------------|
212
- | key | `Symbol` | key of the collection (same as `#attribute`) |
213
- | scheme | `Scheme`, `NilClass`, `Class` | scheme to use if no `&block` is given or `Class` of each item in the |
214
- | allow_empty: | `TrueClass`, `FalseClass` | if true, empty (no key/value present) is allowed |
215
- | expected_type: | `Class`, | forces the validated value to have this type, defaults to `Array`. Use `Object` if either `Array` or `Hash` is fine. |
216
- | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
217
- | &block | `Block` | defines the scheme of the value of this attribute |
210
+ | param | type | description |
211
+ | -------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
212
+ | key | `Symbol` | key of the collection (same as `#attribute`) |
213
+ | scheme | `Scheme`, `NilClass`, `Class` | scheme to use if no `&block` is given or `Class` of each item in the collection |
214
+ | allow_empty: | `TrueClass`, `FalseClass` | if true, empty (no key/value present) is allowed |
215
+ | expected_type: | `Class`, | forces the validated value to have this type, defaults to `Array`. Use `Object` if either `Array` or `Hash` is fine. |
216
+ | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
217
+ | &block | `Block` | defines the scheme of the value of this attribute |
218
218
 
219
219
 
220
220
  #### Collection with an array of string
@@ -253,12 +253,12 @@ MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', nu
253
253
 
254
254
  Expect a link with a required `href: String` attribute
255
255
 
256
- | param | type | description |
257
- |-------|------|-------------|
258
- | key | `Symbol` | key of the link (same as `#attribute`) |
259
- | allow_nil: | `TrueClass`, `FalseClass` | if true, value may be nil |
260
- | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
261
- | &block | `Block` | defines the scheme of the value of this attribute, in addition to the `href` attribute |
256
+ | param | type | description |
257
+ | ---------- | ------------------------- | -------------------------------------------------------------------------------------- |
258
+ | key | `Symbol` | key of the link (same as `#attribute`) |
259
+ | allow_nil: | `TrueClass`, `FalseClass` | if true, value may be nil |
260
+ | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
261
+ | &block | `Block` | defines the scheme of the value of this attribute, in addition to the `href` attribute |
262
262
 
263
263
  #### Links as defined in HAL, JSON-Links and other specs
264
264
  ```Ruby
@@ -266,7 +266,7 @@ class MyMedia
266
266
  include MediaTypes::Dsl
267
267
 
268
268
  validations do
269
- link :_self
269
+ link :self
270
270
  link :image
271
271
  end
272
272
  end
@@ -365,7 +365,7 @@ Allows passing in validation options as a second parameter.
365
365
 
366
366
  Example: `Venue.version(42).validatable?`
367
367
 
368
- Tests wether the current configuration of the schema has a validation defined.
368
+ Tests whether the current configuration of the schema has a validation defined.
369
369
 
370
370
  ### `register`
371
371
 
@@ -403,10 +403,254 @@ Example: `Venue.available_validations`
403
403
 
404
404
  Returns a list of all the schemas that are defined.
405
405
 
406
+ ## Ensuring Your MediaTypes Work
407
+
408
+ ### Overview & Rationale
409
+
410
+ If the MediaTypes you create enforce a specification you _do not expect them to_, it will cause problems that will be very difficult to fix, as other code, which utilises your MediaType, would break when you change the specification. This is because the faulty MediaType definition will start to make other code dependent on the specification it defines. For example, consider what would happen if you release a MediaType which defines an attribute `foo` to be a `String`, and run a server which defines such a specification. Later, you realise you _actually_ wanted `foo` to be `Numeric`. What can you do?
411
+
412
+ Well, during this time, other people started to write code which conformed to the specification defined by the faulty MediaType. So, it's going to be extremely difficult to revert your mistake. For this reason, it is vital that, when using this library, your MediaTypes define the _correct_ specification.
413
+
414
+ To this end, we provide you with a few avenues to check whether MediaTypes define the specifications you actually intend by checking examples of JSON you expect to be compliant/non-compliant with the MediaType definitions you write out.
415
+
416
+ These are as follows:
417
+
418
+ 1. The library provides [two methods](README.md#media-type-checking-in-test-suites) (`assert_pass` and `assert_fail`), which allow specifying JSON fixtures that are compliant (`assert_pass`) or non-compliant (`assert_fail`).
419
+ 2. The library provides a way to validate those fixtures against the MediaType specification with the [`assert_mediatype`](README.md#media-type-checking-in-test-suites) method.
420
+ 3. The library automatically performs a MediaType's checks defined by (1) the first time an object is validated against the MediaType, and throws an error if any of the checks fail.
421
+ 4. The library provides a way to run the checks carried out by (3) on load, using the method [`assert_sane!`](README.md#validation-checks) so that an application will not run if any of the MediaType's checks don't pass.
422
+
423
+ These four options are examined in detail below.
424
+
425
+ ### MediaType Checking in Test Suites
426
+
427
+ The library provides the `assert_mediatype` method, which allows running the checks for a particular `MediaType` within Minitest with `assert_pass` and `assert_fail`.
428
+ If you are using Minitest, you can make `assert_mediatype` available by calling `include MediaTypes::Testing::Assertions` in the test class (e.g. `Minitest::Runnable`):
429
+
430
+ ```ruby
431
+ module Minitest
432
+ class Test < Minitest::Runnable
433
+ include MediaTypes::Testing::Assertions
434
+ end
435
+ end
436
+ ```
437
+
438
+ The example below demonstrates how to use `assert_pass` and `assert_fail` within a MediaType, and how to use the `assert_mediatype` method in MiniTest tests to validate them.
439
+
440
+ ```ruby
441
+ class MyMedia
442
+ include MediaTypes::Dsl
443
+
444
+ def self.organisation
445
+ 'acme'
446
+ end
447
+
448
+ use_name 'test'
449
+
450
+ validations do
451
+ # Using "any Numeric" this MediaType doesn't care what key names you use.
452
+ # However, it does care that those keys point to a Numeric value.
453
+ any Numeric
454
+
455
+ assert_pass '{"foo": 42}'
456
+ assert_pass <<-FIXTURE
457
+ { "foo": 42, "bar": 43 }
458
+ FIXTURE
459
+
460
+ # The keyword "any" means there are no required keys, so having no keys should also pass.
461
+ assert_pass '{}'
462
+
463
+ # This MediaType should not accept anything other then a Numeric value.
464
+ assert_fail <<-FIXTURE
465
+ { "foo": { "bar": "string" } }
466
+ FIXTURE
467
+ assert_fail '{"foo": {}}'
468
+ assert_fail '{"foo": null}'
469
+ assert_fail '{"foo": [42]}'
470
+ end
471
+ end
472
+
473
+ class MyMediaTest < Minitest::Test
474
+ include MediaTypes::Testing::Assertions
475
+
476
+ def test_mediatype_specification
477
+ assert_mediatype MyMedia
478
+ end
479
+ end
480
+
481
+ class MyMediaTest < Minitest::Test
482
+ include MediaTypes::Testing::Assertions
483
+
484
+ def test_mediatype_specification
485
+ assert_mediatype MyMedia
486
+ end
487
+ end
488
+
489
+ ```
490
+
491
+ ### Testing Without Minitest
492
+
493
+ If you are using another testing framework, you will not be able to use the `assert_mediatype` method. Instead, you can test your MediaTypes by using the `assert_sane!` method (documented below) and rescuing the errors it will throw when it fails. The snippet below shows an example adaptation for MiniTest, which you can use as a guide.
494
+
495
+ ```ruby
496
+ def test_mediatype(mediatype)
497
+ mediatype.assert_sane!
498
+ assert mediatype.media_type_validations.scheme.asserted_sane?
499
+ rescue MediaTypes::AssertionError => e
500
+ flunk e.message
501
+ end
502
+ end
503
+ ```
504
+
505
+ ### Validation Checks
506
+
507
+ The `assert_pass` and `assert_fail` methods take a JSON string (as shown below). The first time the `validate!` method is called on a MediaType, the assertions for that media type are run.
508
+ This is done as a last line of defence against introducing faulty MediaTypes into your software. Ideally, you want to carry out these checks on load rather than on a running application. This functionality is provided by the `assert_sane!` method, which can be called on a particular MediaType:
509
+
510
+ ```ruby
511
+ MyMedia.assert_sane!
512
+ # true
513
+ ```
514
+
515
+ ### Intermediate Checks
516
+
517
+ The fixtures provided to the `assert_pass` and `assert_fail` methods are evaluated within the context of the block they are placed in. It's therefore possible to write a test for a (complex) optional attribute, without that test cluttering the fixtures for the entire mediatype.
518
+
519
+ ```ruby
520
+ class MyMedia
521
+ include MediaTypes::Dsl
522
+
523
+ expect_string_keys
524
+
525
+ def self.organisation
526
+ 'acme'
527
+ end
528
+
529
+ use_name 'test'
530
+
531
+ validations do
532
+ attribute :foo, Hash, optional: true do
533
+ attribute :bar, Numeric
534
+
535
+ # This passes, since in this context the "bar" key is required to have a Numeric value.
536
+ assert_pass '{"bar": 42}'
537
+ end
538
+ attribute :rep, Numeric
539
+
540
+ # This passes, since the attribute "foo" is optional.
541
+ assert_pass '{"rep": 42}'
542
+ end
543
+ end
544
+ ```
545
+
546
+ ## Key Type Validation
547
+
548
+ When interacting with Ruby objects defined by your MediaType, you want to avoid getting `nil` values, just because the the wrong key type is being used (e.g. `obj['foo']` instead of `obj[:foo]`).
549
+ To this end, the library provides the ability to specify the expected type of keys in a MediaType; by default symbol keys are expected.
550
+
551
+ ### Setting Key Type Expectations
552
+
553
+ Key type expectations can be set at the module level. Each MediaType within this module will inherit the expectation set by that module.
554
+
555
+ ```ruby
556
+ module Acme
557
+ MediaTypes.expect_string_keys(self)
558
+
559
+ # The MyMedia class expects string keys, as inherited from the Acme module.
560
+ class MyMedia
561
+ include MediaTypes::Dsl
562
+
563
+ def self.organisation
564
+ 'acme'
565
+ end
566
+
567
+ use_name 'test'
568
+
569
+ validations do
570
+ any Numeric
571
+ end
572
+ end
573
+ end
574
+ ```
575
+
576
+ If you validate an object with a different key type than expected, an error will be thrown:
577
+
578
+ ```ruby
579
+ Acme::MyMedia.validate! { "something": 42 }
580
+ # => passes, because all keys are a string
581
+
582
+ Acme::MyMedia.validate! { something: 42 }
583
+ # => throws a ValidationError , because 'something' is a symbol key
584
+ ```
585
+
586
+ ## Overriding Key Type Expectations
587
+
588
+ A key type expectation set by a Module can be overridden by calling either `expect_symbol_keys` or `expect_string_keys` inside the MediaType class.
589
+
590
+ ```ruby
591
+ module Acme
592
+ MediaTypes.expect_string_keys(self)
593
+
594
+ class MyOverridingMedia
595
+ include MediaTypes::Dsl
596
+
597
+ def self.organisation
598
+ 'acme'
599
+ end
600
+
601
+ use_name 'test'
602
+
603
+ # Expect keys to be symbols
604
+ expect_symbol_keys
605
+
606
+ validations do
607
+ any Numeric
608
+ end
609
+ end
610
+ end
611
+ ```
612
+
613
+ Now the MediaType throws an error when string keys are used.
614
+
615
+ ```ruby
616
+ Acme::MyOverridingMedia.validate! { something: 42 }
617
+ # => passes, because all keys are a symbol
618
+
619
+ Acme::MyOverridingMedia.validate! { "something": 42 }
620
+ # => throws a ValidationError , because 'something' is a string key
621
+ ```
622
+
623
+ ### Setting The JSON Parser With The Wrong Key Type
624
+
625
+ If you parse JSON with the wrong key type, as shown below, the resultant object will fail the validations.
626
+
627
+ ```ruby
628
+ class MyMedia
629
+ include MediaTypes::Dsl
630
+
631
+ def self.organisation
632
+ 'acme'
633
+ end
634
+
635
+ use_name 'test'
636
+
637
+ # Expect keys to be symbols
638
+ expect_symbol_keys
639
+
640
+ validations do
641
+ any Numeric
642
+ end
643
+ end
644
+
645
+ json = JSON.parse('{"foo": {}}', { symbolize_names: false })
646
+ # If MyMedia expects symbol keys
647
+ MyMedia.valid?(json)
648
+ # Returns false
649
+ ```
650
+
406
651
  ## Related
407
652
 
408
- - [`MediaTypes::Serialization`](https://github.com/XPBytes/media_types-serialization): :cyclone: Add media types supported serialization using your favourite serializer
409
- - [`MediaTypes::Validation`](https://github.com/XPBytes/media_types-validation): :heavy_exclamation_mark: Response validations according to a media-type
653
+ - [`MediaTypes::Serialization`](https://github.com/XPBytes/media_types-serialization): :cyclone: Add media types supported serialization to Rails.
410
654
 
411
655
  ## Development
412
656