media_types 0.4.1 → 0.5.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
  SHA1:
3
- metadata.gz: ccae096fd19259b025952edea85f433588fbce01
4
- data.tar.gz: 64fed267722b36d17a324eb9ebb436be04bfc412
3
+ metadata.gz: 54061285d1504ab09d4fc7299bf242ad4e0a7529
4
+ data.tar.gz: d1cff5bf120ff2f5cd570887f3e351117466e54e
5
5
  SHA512:
6
- metadata.gz: 118d4c8c2c67070cd0c5469a5330a95b954993db1773a9da633ff0e58370623732fb0236126d64eadc9869ab1ccd612ddfccef8c39dc4ddc4fa0a64c642903ba
7
- data.tar.gz: 68cf8356ab79b25ba2edf5c20cb1dcae36bb2c9ccf278529643aee6a90aec7d7a4d1599e608a689a460962a062dce586a7649d8a0240cb1994cc7de0b3e7e034
6
+ metadata.gz: 283abdbba4639fbabb39223ed943c495289a2a2f607055e1c00d1b789d6612d604d3de5b7bf4d4e5d644acd9e4d46316e2e92319354f71278059f0c42697b5eb
7
+ data.tar.gz: 2a57915b68ebab50f5820ee472499aea29d9bbeaa17f5cab416419c8ab3acba7f094c1934c50e2458b9c3728f71c5c6f845de6ec6e6e55bac666143ff48030dd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # 0.5.0
2
+
3
+ - Change internal representation of key to symbol
4
+ - Change default type from `nil` to `Object`, removing special behaviour for nil
5
+ - Add `Rules` class to handle normalization of keys and handling `rules` (`Scheme`, `Attribute`, etc)
6
+ - Add guard classes to handle guard behaviour (`OutputEmptyGuard`, `OutputTypeGuard` and `RulesExhaustedGuard`)
7
+ - Add `optional:` keywords to most dsl (`attribute`, `collection`, `any`, `link`)
8
+ - Add `Formatter` class to handle formatting of the `Constructable#to_s`
9
+ - Add behaviour to strip leading dot (`.`) or plus (`+`) from `+%<var>` if `var` is nil, fixing weird media types
10
+ - Add behaviour to remove format variable values if format variable is not present, fixing warnings
11
+ - Add `inspect` for most public classes
12
+ - Add second argument for type or scheme to `any` dsl, mimicking `collection`
13
+ - Add tests for most dsl, common permutations
14
+ - Rename `force` to `expected_type`
15
+ - Remove `format_view` behaviour where it adds a dot (`.`) if a view is present
16
+ - Remove special iteration behaviour for `Links` (`link` dsl), allowing them to be optional, or non-exhaustive
17
+ - Raise error if `self.base_format` is not available at time of `Dsl.media_type` call
18
+ - Fix `expected_type` guard for arrays, nil, or arrays with nil.
19
+
1
20
  # 0.4.1
2
21
 
3
22
  - Use strings for `:_links`, matching the other validation keys
data/Gemfile.lock CHANGED
@@ -1,44 +1,44 @@
1
- PATH
2
- remote: .
3
- specs:
4
- media_types (0.4.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.3)
12
- docile (1.3.1)
13
- json (2.1.0)
14
- minitest (5.11.3)
15
- minitest-ci (3.4.0)
16
- minitest (>= 5.0.6)
17
- minitest-reporters (1.3.4)
18
- ansi
19
- builder
20
- minitest (>= 5.0)
21
- ruby-progressbar
22
- rake (10.5.0)
23
- ruby-progressbar (1.10.0)
24
- simplecov (0.16.1)
25
- docile (~> 1.1)
26
- json (>= 1.8, < 3)
27
- simplecov-html (~> 0.10.0)
28
- simplecov-html (0.10.2)
29
-
30
- PLATFORMS
31
- x64-mingw32
32
-
33
- DEPENDENCIES
34
- awesome_print
35
- bundler (~> 1.16)
36
- media_types!
37
- minitest (~> 5.0)
38
- minitest-ci
39
- minitest-reporters
40
- rake (~> 10.0)
41
- simplecov
42
-
43
- BUNDLED WITH
44
- 1.16.4
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ media_types (0.5.0)
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.3)
12
+ docile (1.3.1)
13
+ json (2.1.0)
14
+ minitest (5.11.3)
15
+ minitest-ci (3.4.0)
16
+ minitest (>= 5.0.6)
17
+ minitest-reporters (1.3.4)
18
+ ansi
19
+ builder
20
+ minitest (>= 5.0)
21
+ ruby-progressbar
22
+ rake (10.5.0)
23
+ ruby-progressbar (1.10.0)
24
+ simplecov (0.16.1)
25
+ docile (~> 1.1)
26
+ json (>= 1.8, < 3)
27
+ simplecov-html (~> 0.10.0)
28
+ simplecov-html (0.10.2)
29
+
30
+ PLATFORMS
31
+ x64-mingw32
32
+
33
+ DEPENDENCIES
34
+ awesome_print
35
+ bundler (~> 1.16)
36
+ media_types!
37
+ minitest (~> 5.0)
38
+ minitest-ci
39
+ minitest-reporters
40
+ rake (~> 10.0)
41
+ simplecov
42
+
43
+ BUNDLED WITH
44
+ 1.16.4
data/README.md CHANGED
@@ -1,347 +1,379 @@
1
- # MediaTypes
2
- [![Build Status](https://travis-ci.com/SleeplessByte/media-types-ruby.svg?branch=master)](https://travis-ci.com/SleeplessByte/media-types-ruby)
3
- [![Gem Version](https://badge.fury.io/rb/media_types.svg)](https://badge.fury.io/rb/media_types)
4
- [![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/6f2dc1fb37ecb98c4363/maintainability)](https://codeclimate.com/github/SleeplessByte/media-types-ruby/maintainability)
6
-
7
- ## Installation
8
-
9
- Add this line to your application's Gemfile:
10
-
11
- ```ruby
12
- gem 'media_types'
13
- ```
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install media_types
22
-
23
- ## Usage
24
-
25
- By default there are no media types registered or defined, except for an abstract base type.
26
-
27
- ## Definition
28
- You can define media types by inheriting from this base type, or create your own base type with a class method
29
- `.base_format` that is used to create the final media type string by injecting formatted parameters:
30
-
31
- - `%<type>s`: the type `media_type` received
32
- - `%<version>s`: the version, defaults to `:current_version`
33
- - `%<view>s`: the view, defaults to <empty>
34
- - `%<suffix>s`: the suffix
35
-
36
- ```Ruby
37
- require 'media_types'
38
-
39
- class Venue < MediaTypes::Base
40
- media_type 'venue', defaults: { suffix: :json, version: 2 }
41
-
42
- validations do
43
- attribute :name, String
44
- collection :location do
45
- attribute :latitude, Numeric
46
- attribute :longitude, Numeric
47
- attribute :altitude, AllowNil(Numeric)
48
- end
49
-
50
- link :self
51
- link :route, allow_nil: true
52
-
53
- version 1 do
54
- attribute :name, String
55
- attribute :coords, String
56
- attribute :updated_at, String
57
-
58
- link :self
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
87
- end
88
-
89
- def self.base_format
90
- 'application/vnd.mydomain.%<type>s.v%<version>s%<view>s+%<suffix>s'
91
- end
92
- end
93
- ```
94
-
95
- ## Schema Definitions
96
-
97
- If you define a scheme using `current_scheme { }`, you may use any of the following dsl:
98
-
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
127
-
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
- ```
142
-
143
- ### `any`
144
- Allow for any key. The `&block` defines the Schema for each value.
145
-
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:
290
-
291
- ```Ruby
292
- Venue.valid?({ ... })
293
- # => true if valid, false otherwise
294
-
295
- Venue.validate!({ ... })
296
- # => raises if it's not valid
297
- ```
298
-
299
- ## Formatting for headers
300
- Any media type object can be coerced in valid string to be used with `Content-Type` or `Accept`:
301
-
302
- ```Ruby
303
- Venue.mime_type.to_s
304
- # => "application/vnd.mydomain.venue.v2+json"
305
-
306
- Venue.mime_type.version(1).to_s
307
- # => "application/vnd.mydomain.venue.v1+json"
308
-
309
- Venue.mime_type.version(1).suffix(:xml).to_s
310
- # => "application/vnd.mydomain.venue.v1+xml"
311
-
312
- Venue.mime_type.to_s(0.2)
313
- # => "application/vnd.mydomain.venue.v2+json; q=0.2"
314
-
315
- Venue.mime_type.collection.to_s
316
- # => "application/vnd.mydomain.venue.v2.collection+json"
317
-
318
- Venue.mime_type.view('active').to_s
319
- # => "application/vnd.mydomain.venue.v2.active+json"
320
- ```
321
-
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
-
327
- As long as `action_dispatch` is available, you can register the mime type with `action_dispatch/http/mime_type`:
328
- ```Ruby
329
- Venue.register
330
- # => Mime type is now available using the symbol, or lookup the actual mimetype
331
- ```
332
-
333
- You can do this in the `mime_types` initializer, or anywhere before your controllers are instantiated. Yes, the symbol
334
- (by default `<type>_v<version>_<suffix>`) can now be used in your `format` blocks, or as extension in the url.
335
-
336
- ## Development
337
-
338
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can
339
- also run `bin/console` for an interactive prompt that will allow you to experiment.
340
-
341
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
342
- version number in `version.rb`, call `bundle exec rake release` to create a new git tag, push git commits and tags, and
343
- push the `.gem` file to rubygems.org.
344
-
345
- ## Contributing
346
-
347
- Bug reports and pull requests are welcome on GitHub at [SleeplessByte/media-types-ruby](https://github.com/SleeplessByte/media-types-ruby)
1
+ # MediaTypes
2
+ [![Build Status](https://travis-ci.com/SleeplessByte/media-types-ruby.svg?branch=master)](https://travis-ci.com/SleeplessByte/media-types-ruby)
3
+ [![Gem Version](https://badge.fury.io/rb/media_types.svg)](https://badge.fury.io/rb/media_types)
4
+ [![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/6f2dc1fb37ecb98c4363/maintainability)](https://codeclimate.com/github/SleeplessByte/media-types-ruby/maintainability)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'media_types'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install media_types
22
+
23
+ ## Usage
24
+
25
+ By default there are no media types registered or defined, except for an abstract base type.
26
+
27
+ ## Definition
28
+ You can define media types by inheriting from this base type, or create your own base type with a class method
29
+ `.base_format` that is used to create the final media type string by injecting formatted parameters:
30
+
31
+ - `%<type>s`: the type `media_type` received
32
+ - `%<version>s`: the version, defaults to `:current_version`
33
+ - `%<view>s`: the view, defaults to <empty>
34
+ - `%<suffix>s`: the suffix
35
+
36
+ ```Ruby
37
+ require 'media_types'
38
+
39
+ class Venue < MediaTypes::Base
40
+ media_type 'venue', defaults: { suffix: :json, version: 2 }
41
+
42
+ validations do
43
+ attribute :name, String
44
+ collection :location do
45
+ attribute :latitude, Numeric
46
+ attribute :longitude, Numeric
47
+ attribute :altitude, AllowNil(Numeric)
48
+ end
49
+
50
+ link :self
51
+ link :route, allow_nil: true
52
+
53
+ version 1 do
54
+ attribute :name, String
55
+ attribute :coords, String
56
+ attribute :updated_at, String
57
+
58
+ link :self
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
87
+ end
88
+
89
+ def self.base_format
90
+ 'application/vnd.mydomain.%<type>s.v%<version>.s%<view>s+%<suffix>s'
91
+ end
92
+ end
93
+ ```
94
+
95
+ ## Schema Definitions
96
+
97
+ If you define a scheme using `current_scheme { }`, you may use any of the following dsl:
98
+
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
+ | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
109
+ | &block | `Block` | defines the scheme of the value of this attribute |
110
+
111
+ #### Add an attribute named foo, expecting a string
112
+ ```Ruby
113
+ require 'media_types'
114
+
115
+ class MyMedia
116
+ include MediaTypes::Dsl
117
+
118
+ validations do
119
+ attribute :foo, String
120
+ end
121
+ end
122
+
123
+ MyMedia.valid?({ foo: 'my-string' })
124
+ # => true
125
+ ```
126
+
127
+ #### Add an attribute named foo, expecting nested scheme
128
+
129
+ ```Ruby
130
+ class MyMedia
131
+ include MediaTypes::Dsl
132
+
133
+ validations do
134
+ attribute :foo do
135
+ attribute :bar, String
136
+ end
137
+ end
138
+ end
139
+
140
+ MyMedia.valid?({ foo: { bar: 'my-string' }})
141
+ # => true
142
+ ```
143
+
144
+ ### `any`
145
+ Allow for any key. The `&block` defines the Schema for each value.
146
+
147
+ | param | type | description |
148
+ |-------|------|-------------|
149
+ | scheme | `Scheme`, `NilClass` | scheme to use if no `&block` is given |
150
+ | allow_empty: | `TrueClass`, `FalsClass` | if true, empty (no key/value present) is allowed |
151
+ | expected_type: | `Class`, | forces the validated value to have this type, defaults to `Hash`. Use `Object` if either `Hash` or `Array` is fine |
152
+ | &block | `Block` | defines the scheme of the value of this attribute |
153
+
154
+ #### Add a collection named foo, expecting any key with a defined value
155
+ ```Ruby
156
+ class MyMedia
157
+ include MediaTypes::Dsl
158
+
159
+ validations do
160
+ collection :foo do
161
+ any do
162
+ attribute :bar, String
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ MyMedia.valid?({ foo: [{ anything: { bar: 'my-string' }, other_thing: { bar: 'other-string' } }] })
169
+ # => true
170
+ ````
171
+
172
+ ### `not_strict`
173
+ Allow for extra keys in the schema/collection even when passing `strict: true` to `#validate!`
174
+
175
+ #### Allow for extra keys in collection
176
+
177
+ ```Ruby
178
+ class MyMedia
179
+ include MediaTypes::Dsl
180
+
181
+ validations do
182
+ collection :foo do
183
+ attribute :required, String
184
+ not_strict
185
+ end
186
+ end
187
+ end
188
+
189
+ MyMedia.valid?({ foo: [{ required: 'test', bar: 42 }] })
190
+ # => true
191
+ ```
192
+
193
+ ### `collection`
194
+ Expect a collection such as an array or hash. The `&block` defines the Schema for each item in that collection.
195
+
196
+ | param | type | description |
197
+ |-------|------|-------------|
198
+ | key | `Symbol` | key of the collection (same as `#attribute`) |
199
+ | scheme | `Scheme`, `NilClass`, `Class` | scheme to use if no `&block` is given or `Class` of each item in the |
200
+ | allow_empty: | `TrueClass`, `FalseClass` | if true, empty (no key/value present) is allowed |
201
+ | expected_type: | `Class`, | forces the validated value to have this type, defaults to `Array`. Use `Object` if either `Array` or `Hash` is fine. |
202
+ | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
203
+ | &block | `Block` | defines the scheme of the value of this attribute |
204
+
205
+
206
+ #### Collection with an array of string
207
+ ```Ruby
208
+ class MyMedia
209
+ include MediaTypes::Dsl
210
+
211
+ validations do
212
+ collection :foo, String
213
+ end
214
+ end
215
+
216
+ MyMedia.valid?({ collection: ['foo', 'bar'] })
217
+ # => true
218
+ ```
219
+
220
+ #### Collection with defined scheme
221
+
222
+ ```Ruby
223
+ class MyMedia
224
+ include MediaTypes::Dsl
225
+
226
+ validations do
227
+ collection :foo do
228
+ attribute :required, String
229
+ attribute :number, Numeric
230
+ end
231
+ end
232
+ end
233
+
234
+ MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
235
+ # => true
236
+ ```
237
+
238
+ ### `link`
239
+
240
+ Expect a link with a required `href: String` attribute
241
+
242
+ | param | type | description |
243
+ |-------|------|-------------|
244
+ | key | `Symbol` | key of the link (same as `#attribute`) |
245
+ | allow_nil: | `TrueClass`, `FalseClass` | if true, value may be nil |
246
+ | optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
247
+ | &block | `Block` | defines the scheme of the value of this attribute, in addition to the `href` attribute |
248
+
249
+ #### Links as defined in HAL, JSON-Links and other specs
250
+ ```Ruby
251
+ class MyMedia
252
+ include MediaTypes::Dsl
253
+
254
+ validations do
255
+ link :_self
256
+ link :image
257
+ end
258
+ end
259
+
260
+ MyMedia.valid?({ _links: { self: { href: 'https://example.org/s' }, image: { href: 'https://image.org/i' }} })
261
+ # => true
262
+ ```
263
+
264
+
265
+ #### Link with extra attributes
266
+ ```Ruby
267
+ class MyMedia
268
+ include MediaTypes::Dsl
269
+
270
+ validations do
271
+ link :image do
272
+ attribute :templated, TrueClass
273
+ end
274
+ end
275
+ end
276
+
277
+ MyMedia.valid?({ _links: { self: { href: 'https://example.org/s' }, image: { href: 'https://image.org/i' }} })
278
+ # => true
279
+ ```
280
+
281
+ #### Link with extra attributes
282
+ ```Ruby
283
+ class MyMedia
284
+ include MediaTypes::Dsl
285
+
286
+ validations do
287
+ link :image do
288
+ attribute :templated, TrueClass
289
+ end
290
+ end
291
+ end
292
+
293
+ MyMedia.valid?({ _links: { image: { href: 'https://image.org/{md5}', templated: true }} })
294
+ # => true
295
+ ```
296
+
297
+ ## Validation
298
+ If your type has a validations, you can now use this media type for validation:
299
+
300
+ ```Ruby
301
+ Venue.valid?({
302
+ #...
303
+ })
304
+ # => true if valid, false otherwise
305
+
306
+ Venue.validate!({
307
+ # /*...*/
308
+ })
309
+ # => raises if it's not valid
310
+ ```
311
+
312
+ If an array is passed, check the scheme for each value, unless the scheme is defined as expecting a hash:
313
+ ```Ruby
314
+ expected_hash = Scheme.new(expected_type: Hash) { attribute(:foo) }
315
+ expected_object = Scheme.new { attribute(:foo) }
316
+
317
+ expected_hash.valid?({ foo: 'string' })
318
+ # => true
319
+
320
+ expected_hash.valid?([{ foo: 'string' }])
321
+ # => false
322
+
323
+
324
+ expected_object.valid?({ foo: 'string' })
325
+ # => true
326
+
327
+ expected_object.valid?([{ foo: 'string' }])
328
+ # => true
329
+ ```
330
+
331
+ ## Formatting for headers
332
+ Any media type object can be coerced in valid string to be used with `Content-Type` or `Accept`:
333
+
334
+ ```Ruby
335
+ Venue.mime_type.to_s
336
+ # => "application/vnd.mydomain.venue.v2+json"
337
+
338
+ Venue.mime_type.version(1).to_s
339
+ # => "application/vnd.mydomain.venue.v1+json"
340
+
341
+ Venue.mime_type.version(1).suffix(:xml).to_s
342
+ # => "application/vnd.mydomain.venue.v1+xml"
343
+
344
+ Venue.mime_type.to_s(0.2)
345
+ # => "application/vnd.mydomain.venue.v2+json; q=0.2"
346
+
347
+ Venue.mime_type.collection.to_s
348
+ # => "application/vnd.mydomain.venue.v2.collection+json"
349
+
350
+ Venue.mime_type.view('active').to_s
351
+ # => "application/vnd.mydomain.venue.v2.active+json"
352
+ ```
353
+
354
+ ## Register in Rails or Rack
355
+ Define a `registrations` block on your media type, indicating the symbol for the base type (`registrations :symbol do`)
356
+ and inside use the registrations dsl to define which media types to register. `versions array_of_numbers` determines which versions,
357
+ `suffix name` adds a suffix, `type_alias name` adds an alias and `view name, symbol` adds a view.
358
+
359
+ As long as `action_dispatch` is available, you can register the mime type with `action_dispatch/http/mime_type`:
360
+ ```Ruby
361
+ Venue.register
362
+ # => Mime type is now available using the symbol, or lookup the actual mimetype
363
+ ```
364
+
365
+ You can do this in the `mime_types` initializer, or anywhere before your controllers are instantiated. Yes, the symbol
366
+ (by default `<type>_v<version>_<suffix>`) can now be used in your `format` blocks, or as extension in the url.
367
+
368
+ ## Development
369
+
370
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can
371
+ also run `bin/console` for an interactive prompt that will allow you to experiment.
372
+
373
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
374
+ version number in `version.rb`, call `bundle exec rake release` to create a new git tag, push git commits and tags, and
375
+ push the `.gem` file to rubygems.org.
376
+
377
+ ## Contributing
378
+
379
+ Bug reports and pull requests are welcome on GitHub at [SleeplessByte/media-types-ruby](https://github.com/SleeplessByte/media-types-ruby)