media_types 0.6.2 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b854726c0783d1e7f27c66a195362a9df615500fb0bc329a935aa589d3451138
4
- data.tar.gz: 3699e6ea389a304a2a7970911a39ae269e0705b3283c8b816868f1ba76abc6fa
3
+ metadata.gz: 8285f897870c9a66139c5129db60c7abf31f870ef20103e6d21da6be99c139b8
4
+ data.tar.gz: a62bbb54c1e1de59cdbef2c98050f1aa0d040dc6aa15a7559aa8e016014d26b0
5
5
  SHA512:
6
- metadata.gz: 05a9e6bb7d2cf222148750830b4efb69fc73a7b955e4a7cf51de6dbe3ed4866187cc498c7b11c8060f0a3dc53eac76fa7bc762049ed6174bdaccc0ea3fa118c7
7
- data.tar.gz: c811c45d8ed2355a39f49f924d09a6a3326abe715e86b5ce4634d6a7dc1d2a18c565e6f1f6de60a769aa2fd6a863bd328da82a15ee3a8e6eaded39beab35856d
6
+ metadata.gz: 132ca0f0f8acf1dcd915c75c7b7b283ee3cc3a896d3fb53acffd8adc958300535bf7dde1d030e26865b317905c5da62ad18e507dbb1f04829ef5582bd4b187b3
7
+ data.tar.gz: ee0d5bd2f3e51f492d5530bbfa45e1acfb067ebc2a690a4b4cdf02d1284792bed60eebfaa6757c0b8a36fb520566932da784c9434d235fa59fb7c58f97231da3
@@ -0,0 +1,20 @@
1
+ name: Ruby
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v1
12
+ - name: Set up Ruby 2.6
13
+ uses: actions/setup-ruby@v1
14
+ with:
15
+ ruby-version: 2.6.x
16
+ - name: Build and test with Rake
17
+ run: |
18
+ gem install bundler
19
+ bundle install --jobs 4 --retry 3
20
+ bundle exec rake
@@ -1,3 +1,16 @@
1
+ # 1.0.0
2
+ - Added the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
3
+ - `media_type` has been replaced with `use_name`.
4
+ - It is no longer possible to set a default version. Please use `version <x> do` instead.
5
+ - 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.
6
+ - `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
7
+ - Added the `empty` validation to mark an empty object as valid.
8
+ - Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
9
+ - Added `version(x)` and `view(x)` functions.
10
+ - Added an `available_validations` functions that returns all defined validations.
11
+ - Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
12
+ - Fixed an issue where undefined validations would accept an empty object.
13
+
1
14
  # 0.6.2
2
15
 
3
16
  - Fix handling empty collections
@@ -1,109 +1,114 @@
1
- PATH
2
- remote: .
3
- specs:
4
- media_types (0.6.2)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- actionpack (5.2.3)
10
- actionview (= 5.2.3)
11
- activesupport (= 5.2.3)
12
- rack (~> 2.0)
13
- rack-test (>= 0.6.3)
14
- rails-dom-testing (~> 2.0)
15
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
16
- actionview (5.2.3)
17
- activesupport (= 5.2.3)
18
- builder (~> 3.1)
19
- erubi (~> 1.4)
20
- rails-dom-testing (~> 2.0)
21
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
22
- activesupport (5.2.3)
23
- concurrent-ruby (~> 1.0, >= 1.0.2)
24
- i18n (>= 0.7, < 2)
25
- minitest (~> 5.1)
26
- tzinfo (~> 1.1)
27
- addressable (2.6.0)
28
- public_suffix (>= 2.0.2, < 4.0)
29
- ansi (1.5.0)
30
- awesome_print (1.8.0)
31
- builder (3.2.3)
32
- concurrent-ruby (1.1.5)
33
- crass (1.0.4)
34
- docile (1.3.1)
35
- domain_name (0.5.20180417)
36
- unf (>= 0.0.5, < 1.0.0)
37
- erubi (1.8.0)
38
- http (4.1.1)
39
- addressable (~> 2.3)
40
- http-cookie (~> 1.0)
41
- http-form_data (~> 2.0)
42
- http_parser.rb (~> 0.6.0)
43
- http-cookie (1.0.3)
44
- domain_name (~> 0.5)
45
- http-form_data (2.1.1)
46
- http_parser.rb (0.6.0)
47
- i18n (1.6.0)
48
- concurrent-ruby (~> 1.0)
49
- json (2.2.0)
50
- loofah (2.2.3)
51
- crass (~> 1.0.2)
52
- nokogiri (>= 1.5.9)
53
- mini_portile2 (2.4.0)
54
- minitest (5.11.3)
55
- minitest-ci (3.4.0)
56
- minitest (>= 5.0.6)
57
- minitest-reporters (1.3.6)
58
- ansi
59
- builder
60
- minitest (>= 5.0)
61
- ruby-progressbar
62
- nokogiri (1.10.3)
63
- mini_portile2 (~> 2.4.0)
64
- nokogiri (1.10.3-x64-mingw32)
65
- mini_portile2 (~> 2.4.0)
66
- oj (3.7.12)
67
- public_suffix (3.0.3)
68
- rack (2.0.6)
69
- rack-test (1.1.0)
70
- rack (>= 1.0, < 3)
71
- rails-dom-testing (2.0.3)
72
- activesupport (>= 4.2.0)
73
- nokogiri (>= 1.6)
74
- rails-html-sanitizer (1.0.4)
75
- loofah (~> 2.2, >= 2.2.2)
76
- rake (12.3.2)
77
- ruby-progressbar (1.10.0)
78
- simplecov (0.16.1)
79
- docile (~> 1.1)
80
- json (>= 1.8, < 3)
81
- simplecov-html (~> 0.10.0)
82
- simplecov-html (0.10.2)
83
- thread_safe (0.3.6)
84
- tzinfo (1.2.5)
85
- thread_safe (~> 0.1)
86
- unf (0.1.4)
87
- unf_ext
88
- unf_ext (0.0.7.5)
89
- unf_ext (0.0.7.5-x64-mingw32)
90
-
91
- PLATFORMS
92
- ruby
93
- x64-mingw32
94
-
95
- DEPENDENCIES
96
- actionpack
97
- awesome_print
98
- bundler (~> 2)
99
- http
100
- media_types!
101
- minitest (~> 5.0)
102
- minitest-ci
103
- minitest-reporters
104
- oj
105
- rake (~> 12.3)
106
- simplecov
107
-
108
- BUNDLED WITH
109
- 2.0.1
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ media_types (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actionpack (5.2.4)
10
+ actionview (= 5.2.4)
11
+ activesupport (= 5.2.4)
12
+ rack (~> 2.0)
13
+ rack-test (>= 0.6.3)
14
+ rails-dom-testing (~> 2.0)
15
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
16
+ actionview (5.2.4)
17
+ activesupport (= 5.2.4)
18
+ builder (~> 3.1)
19
+ erubi (~> 1.4)
20
+ rails-dom-testing (~> 2.0)
21
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
22
+ activesupport (5.2.4)
23
+ concurrent-ruby (~> 1.0, >= 1.0.2)
24
+ i18n (>= 0.7, < 2)
25
+ minitest (~> 5.1)
26
+ tzinfo (~> 1.1)
27
+ addressable (2.7.0)
28
+ public_suffix (>= 2.0.2, < 5.0)
29
+ ansi (1.5.0)
30
+ awesome_print (1.8.0)
31
+ builder (3.2.3)
32
+ concurrent-ruby (1.1.5)
33
+ crass (1.0.5)
34
+ docile (1.3.2)
35
+ domain_name (0.5.20190701)
36
+ unf (>= 0.0.5, < 1.0.0)
37
+ erubi (1.9.0)
38
+ ffi (1.11.1)
39
+ ffi (1.11.1-x64-mingw32)
40
+ ffi-compiler (1.0.1)
41
+ ffi (>= 1.0.0)
42
+ rake
43
+ http (4.2.0)
44
+ addressable (~> 2.3)
45
+ http-cookie (~> 1.0)
46
+ http-form_data (~> 2.0)
47
+ http-parser (~> 1.2.0)
48
+ http-cookie (1.0.3)
49
+ domain_name (~> 0.5)
50
+ http-form_data (2.1.1)
51
+ http-parser (1.2.1)
52
+ ffi-compiler (>= 1.0, < 2.0)
53
+ i18n (1.7.0)
54
+ concurrent-ruby (~> 1.0)
55
+ json (2.2.0)
56
+ loofah (2.4.0)
57
+ crass (~> 1.0.2)
58
+ nokogiri (>= 1.5.9)
59
+ mini_portile2 (2.4.0)
60
+ minitest (5.13.0)
61
+ minitest-ci (3.4.0)
62
+ minitest (>= 5.0.6)
63
+ minitest-reporters (1.4.2)
64
+ ansi
65
+ builder
66
+ minitest (>= 5.0)
67
+ ruby-progressbar
68
+ nokogiri (1.10.7)
69
+ mini_portile2 (~> 2.4.0)
70
+ nokogiri (1.10.7-x64-mingw32)
71
+ mini_portile2 (~> 2.4.0)
72
+ oj (3.10.0)
73
+ public_suffix (4.0.1)
74
+ rack (2.0.7)
75
+ rack-test (1.1.0)
76
+ rack (>= 1.0, < 3)
77
+ rails-dom-testing (2.0.3)
78
+ activesupport (>= 4.2.0)
79
+ nokogiri (>= 1.6)
80
+ rails-html-sanitizer (1.3.0)
81
+ loofah (~> 2.3)
82
+ rake (13.0.1)
83
+ ruby-progressbar (1.10.1)
84
+ simplecov (0.17.1)
85
+ docile (~> 1.1)
86
+ json (>= 1.8, < 3)
87
+ simplecov-html (~> 0.10.0)
88
+ simplecov-html (0.10.2)
89
+ thread_safe (0.3.6)
90
+ tzinfo (1.2.5)
91
+ thread_safe (~> 0.1)
92
+ unf (0.1.4)
93
+ unf_ext
94
+ unf_ext (0.0.7.6)
95
+
96
+ PLATFORMS
97
+ ruby
98
+ x64-mingw32
99
+
100
+ DEPENDENCIES
101
+ actionpack
102
+ awesome_print
103
+ bundler (~> 2)
104
+ http
105
+ media_types!
106
+ minitest (~> 5.0)
107
+ minitest-ci
108
+ minitest-reporters
109
+ oj
110
+ rake (~> 13.0)
111
+ simplecov
112
+
113
+ BUNDLED WITH
114
+ 2.0.1
data/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
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).
8
8
 
9
+ This library makes it easy to define schemas that can be used to validate JSON objects based on their Content-Type.
10
+
9
11
  ## Installation
10
12
 
11
13
  Add this line to your application's Gemfile:
@@ -24,15 +26,33 @@ Or install it yourself as:
24
26
 
25
27
  ## Usage
26
28
 
27
- By default there are no media types registered or defined, except for an abstract base type.
29
+ Define a validation:
30
+
31
+ ```ruby
32
+ require 'media_types'
33
+
34
+ module Acme
35
+ MediaTypes::set_organisation Acme, 'acme'
36
+
37
+ class FooValidator
38
+ include MediaTypes::Dsl
39
+
40
+ use_name 'foo'
28
41
 
29
- ## Definition
30
- You can define media types by inheriting from this base type, or create your own base type with a class method `.base_format` that is used to create the final media type string by injecting formatted parameters:
42
+ validations do
43
+ attribute :foo, String
44
+ end
45
+ end
46
+ end
47
+ ```
31
48
 
32
- - `%<type>s`: the type `media_type` received
33
- - `%<version>s`: the version, defaults to `:current_version`
34
- - `%<view>s`: the view, defaults to <empty>
35
- - `%<suffix>s`: the suffix
49
+ Validate an object:
50
+
51
+ ```ruby
52
+ Acme::FooValidator.validate!({ foo: 'bar' })
53
+ ```
54
+
55
+ ## Full example
36
56
 
37
57
  ```Ruby
38
58
  require 'media_types'
@@ -40,22 +60,24 @@ require 'media_types'
40
60
  class Venue
41
61
  include MediaTypes::Dsl
42
62
 
43
- def self.base_format
44
- 'application/vnd.mydomain.%<type>s.v%<version>s.%<view>s+%<suffix>s'
63
+ def self.organisation
64
+ 'mydomain'
45
65
  end
46
66
 
47
- media_type 'venue', defaults: { suffix: :json, version: 2 }
67
+ media_type 'venue', defaults: { suffix: :json }
48
68
 
49
69
  validations do
50
- attribute :name, String
51
- collection :location do
52
- attribute :latitude, Numeric
53
- attribute :longitude, Numeric
54
- attribute :altitude, AllowNil(Numeric)
55
- end
70
+ version 2 do
71
+ attribute :name, String
72
+ collection :location do
73
+ attribute :latitude, Numeric
74
+ attribute :longitude, Numeric
75
+ attribute :altitude, AllowNil(Numeric)
76
+ end
56
77
 
57
- link :self
58
- link :route, allow_nil: true
78
+ link :self
79
+ link :route, allow_nil: true
80
+ end
59
81
 
60
82
  version 1 do
61
83
  attribute :name, String
@@ -97,7 +119,7 @@ end
97
119
 
98
120
  ## Schema Definitions
99
121
 
100
- If you define a scheme using `current_scheme { }`, you may use any of the following dsl:
122
+ If you include 'MediaTypes::Dsl' in your class you can use the following functions within a `validation do` block to define your schema:
101
123
 
102
124
  ### `attribute`
103
125
 
@@ -315,25 +337,25 @@ expected_object.valid?([{ foo: 'string' }])
315
337
  ```
316
338
 
317
339
  ## Formatting for headers
318
- Any media type object can be coerced in valid string to be used with `Content-Type` or `Accept`:
340
+ Any media type object can be converted in valid string to be used with `Content-Type` or `Accept`:
319
341
 
320
342
  ```Ruby
321
- Venue.mime_type.to_s
343
+ Venue.mime_type.identifier
322
344
  # => "application/vnd.mydomain.venue.v2+json"
323
345
 
324
- Venue.mime_type.version(1).to_s
346
+ Venue.mime_type.version(1).identifier
325
347
  # => "application/vnd.mydomain.venue.v1+json"
326
348
 
327
- Venue.mime_type.version(1).suffix(:xml).to_s
349
+ Venue.mime_type.version(1).suffix(:xml).identifier
328
350
  # => "application/vnd.mydomain.venue.v1+xml"
329
351
 
330
352
  Venue.mime_type.to_s(0.2)
331
353
  # => "application/vnd.mydomain.venue.v2+json; q=0.2"
332
354
 
333
- Venue.mime_type.collection.to_s
355
+ Venue.mime_type.collection.identifier
334
356
  # => "application/vnd.mydomain.venue.v2.collection+json"
335
357
 
336
- Venue.mime_type.view('active').to_s
358
+ Venue.mime_type.view('active').identifier
337
359
  # => "application/vnd.mydomain.venue.v2.active+json"
338
360
  ```
339
361
 
@@ -374,6 +396,64 @@ Load the `http` integration and call `.register` on all media types you want to
374
396
 
375
397
  Currently uses `oj` under the hood and this can not be changed.
376
398
 
399
+ ## API
400
+
401
+ A defined schema has the following functions available:
402
+
403
+ ### `valid?`
404
+
405
+ Example: `Venue.valid?({ foo: 'bar' })`
406
+
407
+ Allows passing in validation options as a second parameter.
408
+
409
+ ### `validate!`
410
+
411
+ Example: `Venue.validate!({ foo: 'bar' })`
412
+
413
+ Allows passing in validation options as a second parameter.
414
+
415
+ ### `validatable?`
416
+
417
+ Example: `Venue.version(42).validatable?`
418
+
419
+ Tests wether the current configuration of the schema has a validation defined.
420
+
421
+ ### `register`
422
+
423
+ Example: `Venue.register`
424
+
425
+ Registers the media type to the registry.
426
+
427
+ ### `view`
428
+
429
+ Example: `Venue.view('create')`
430
+
431
+ Returns a schema validator configured with the specified view.
432
+
433
+ ### `version`
434
+
435
+ Example: `Venue.version(42)`
436
+
437
+ Returns a schema validator configured with the specified version.
438
+
439
+ ### `suffix`
440
+
441
+ Example: `Venue.suffix(:json)`
442
+
443
+ Returns a schema validator configured with the specified suffix.
444
+
445
+ ### `identifier`
446
+
447
+ Example: `Venue.version(2).identifier` (returns `'application/vnd.application.venue.v2'`)
448
+
449
+ Returns the IANA compatible [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the configured schema.
450
+
451
+ ### `available_validations`
452
+
453
+ Example: `Venue.available_validations`
454
+
455
+ Returns a list of all the schemas that are defined.
456
+
377
457
  ## Related
378
458
 
379
459
  - [`MediaTypes::Serialization`](https://github.com/XPBytes/media_types-serialization): :cyclone: Add media types supported serialization using your favourite serializer
@@ -12,6 +12,19 @@ require 'media_types/views'
12
12
  require 'media_types/integrations'
13
13
 
14
14
  module MediaTypes
15
+ def self.set_organisation(mod, organisation)
16
+ @organisation_prefixes ||= {}
17
+ @organisation_prefixes[mod.name] = organisation
18
+ end
19
+
20
+ def self.get_organisation(mod)
21
+ name = mod.name
22
+ prefixes = @organisation_prefixes.keys.select { |p| name.start_with? p }
23
+ return nil unless prefixes.any?
24
+ best = prefixes.max_by { |p| p.length }
25
+
26
+ @organisation_prefixes[best]
27
+ end
15
28
  end
16
29
 
17
30
 
@@ -73,20 +73,35 @@ module MediaTypes
73
73
  to_str.split(pattern, *limit)
74
74
  end
75
75
 
76
+ def as_key
77
+ [type, view, version, suffix]
78
+ end
79
+
76
80
  def hash
77
- to_str.hash
81
+ as_key.hash
78
82
  end
79
83
 
80
84
  def to_str(qualifier = nil)
81
- # TODO: remove warning by slicing out these arguments if they don't appear in the format
82
85
  qualified(
83
86
  qualifier,
84
- Formatter.call(opts)
87
+ __getobj__.media_type_name_for.call(
88
+ type: opts[:type],
89
+ view: opts[:view],
90
+ version: opts[:version],
91
+ suffix: opts[:suffix],
92
+ )
85
93
  )
86
94
  end
95
+
96
+ def available_validations
97
+ return [] if !validatable?
98
+ [self]
99
+ end
87
100
 
88
101
  def valid?(output, **validation_opts)
89
- __getobj__.valid?(
102
+ raise ArgumentError, "Unable to validate #{to_s} type without a corresponding validation. Please mark objects that should be empty with 'empty'." unless validatable?
103
+
104
+ __getobj__.valid_unsafe?(
90
105
  output,
91
106
  self,
92
107
  **validation_opts
@@ -94,7 +109,9 @@ module MediaTypes
94
109
  end
95
110
 
96
111
  def validate!(output, **validation_opts)
97
- __getobj__.validate!(
112
+ raise ArgumentError, "Unable to validate #{to_s} type without a corresponding validation. Please mark objects that should be empty with 'empty'." unless validatable?
113
+
114
+ __getobj__.validate_unsafe!(
98
115
  output,
99
116
  self,
100
117
  **validation_opts
@@ -102,11 +119,14 @@ module MediaTypes
102
119
  end
103
120
 
104
121
  def validatable?
122
+ return false unless media_type_combinations.include? as_key
123
+
105
124
  __getobj__.validatable?(self)
106
125
  end
107
126
 
108
127
  alias inspect to_str
109
128
  alias to_s to_str
129
+ alias identifier to_str
110
130
 
111
131
  private
112
132
 
@@ -7,14 +7,18 @@ require 'media_types/validations'
7
7
 
8
8
  module MediaTypes
9
9
  module Dsl
10
+
10
11
  def self.included(base)
11
12
  base.extend ClassMethods
12
13
  base.class_eval do
13
14
  class << self
15
+ attr_accessor :media_type_name_for, :media_type_combinations
16
+
14
17
  private
15
18
 
16
19
  attr_accessor :media_type_constructable, :symbol_base, :media_type_registrar, :media_type_validations
17
20
  end
21
+ base.media_type_combinations = Set.new
18
22
  end
19
23
  end
20
24
 
@@ -26,18 +30,26 @@ module MediaTypes
26
30
  end
27
31
  end
28
32
 
29
- def valid?(output, media_type = to_constructable, **opts)
30
- validations.find(String(media_type)).valid?(output, backtrace: ['.'], **opts)
33
+ def valid?(output, **opts)
34
+ to_constructable.valid?(output, **opts)
35
+ end
36
+
37
+ def valid_unsafe?(output, media_type = to_constructable, **opts)
38
+ validations.find(media_type).valid?(output, backtrace: ['.'], **opts)
39
+ end
40
+
41
+ def validate!(output, **opts)
42
+ to_constructable.validate!(output, **opts)
31
43
  end
32
44
 
33
- def validate!(output, media_type = to_constructable, **opts)
34
- validations.find(String(media_type)).validate(output, backtrace: ['.'], **opts)
45
+ def validate_unsafe!(output, media_type = to_constructable, **opts)
46
+ validations.find(media_type).validate(output, backtrace: ['.'], **opts)
35
47
  end
36
48
 
37
49
  def validatable?(media_type = to_constructable)
38
50
  return false unless validations
39
51
 
40
- validations.find(String(media_type), -> { nil })
52
+ validations.find(media_type, -> { nil })
41
53
  end
42
54
 
43
55
  def register
@@ -46,22 +58,58 @@ module MediaTypes
46
58
  registerable
47
59
  end
48
60
  end
61
+
62
+ def view(v)
63
+ to_constructable.view(v)
64
+ end
65
+ def version(v)
66
+ to_constructable.version(v)
67
+ end
68
+ def suffix(s)
69
+ to_constructable.suffix(s)
70
+ end
49
71
 
50
- private
72
+ def identifier_format
73
+ self.media_type_name_for = Proc.new do |type:, view:, version:, suffix:|
74
+ yield(type: type, view: view, version: version, suffix: suffix)
75
+ end
76
+ end
51
77
 
52
- def media_type(name, defaults: {})
78
+ def identifier
79
+ to_constructable.to_s
80
+ end
53
81
 
54
- unless defined?(:base_format)
55
- define_method(:base_format) do
56
- raise format('Implement the class method "base_format" in %<klass>s', klass: self)
57
- end
82
+ def available_validations
83
+ self.media_type_combinations.map do |a|
84
+ _, view, version, suffix = a
85
+ view(view).version(version).suffix(suffix)
58
86
  end
87
+ end
59
88
 
60
- self.media_type_constructable = Constructable.new(self, format: base_format, type: name)
61
- .version(defaults.fetch(:version) { nil })
62
- .suffix(defaults.fetch(:suffix) { nil })
63
- .view(defaults.fetch(:view) { nil })
64
- self
89
+ private
90
+
91
+ def use_name(name, defaults: {})
92
+ if self.media_type_name_for.nil?
93
+ self.media_type_name_for = Proc.new do |type:, view:, version:, suffix:|
94
+ resolved_org = nil
95
+ if defined?(organisation)
96
+ resolved_org = organisation
97
+ else
98
+ resolved_org = MediaTypes::get_organisation(self)
99
+
100
+ raise format('Implement the class method "organisation" in %<klass>s or specify a global organisation using MediaTypes::set_organisation', klass: self) if resolved_org.nil?
101
+ end
102
+ raise ArgumentError, 'Unable to create a name for a schema with a nil name.' if type.nil?
103
+ raise ArgumentError, 'Unable to create a name for a schema with a nil organisation.' if resolved_org.nil?
104
+
105
+ result = "application/vnd.#{resolved_org}.#{type}"
106
+ result += ".v#{version}" unless version.nil?
107
+ result += ".#{view}" unless view.nil?
108
+ result += "+#{suffix}" unless suffix.nil?
109
+ result
110
+ end
111
+ end
112
+ self.media_type_constructable = Constructable.new(self, type: name).suffix(defaults.fetch(:suffix) { nil })
65
113
  end
66
114
 
67
115
  def defaults(&block)
@@ -17,7 +17,12 @@ require 'media_types/scheme/output_empty_guard'
17
17
  require 'media_types/scheme/output_type_guard'
18
18
  require 'media_types/scheme/rules_exhausted_guard'
19
19
 
20
+ require 'json'
21
+
20
22
  module MediaTypes
23
+ class AssertionError < StandardError
24
+ end
25
+
21
26
  ##
22
27
  # Media Type Schemes can validate content to a media type, by itself. Used by the `validations` dsl.
23
28
  #
@@ -346,6 +351,21 @@ module MediaTypes
346
351
  end.link(*args, **opts, &block)
347
352
  end
348
353
 
354
+ ##
355
+ # Mark object as a valid empty object
356
+ #
357
+ # @example Empty object
358
+ #
359
+ # class MyMedia
360
+ # include MediaTypes::Dsl
361
+ #
362
+ # validations do
363
+ # empty
364
+ # end
365
+ # end
366
+ def empty
367
+ end
368
+
349
369
  def inspect(indentation = 0)
350
370
  tabs = ' ' * indentation
351
371
  [
@@ -355,6 +375,23 @@ module MediaTypes
355
375
  ].join("\n")
356
376
  end
357
377
 
378
+ def assert_pass(fixture)
379
+ json = JSON.parse(fixture)
380
+
381
+ validate(json)
382
+ end
383
+
384
+ def assert_fail(fixture)
385
+ json = JSON.parse(fixture)
386
+
387
+ begin
388
+ validate(json)
389
+ rescue MediaTypes::Scheme::ValidationError
390
+ return
391
+ end
392
+ raise AssertionError
393
+ end
394
+
358
395
  private
359
396
 
360
397
  attr_accessor :rules
@@ -25,7 +25,7 @@ module MediaTypes
25
25
  #
26
26
  def initialize(media_type, registry = {}, scheme = Scheme.new, &block)
27
27
  self.media_type = media_type
28
- self.registry = registry.merge!(media_type.to_s => scheme)
28
+ self.registry = registry.merge!(media_type.as_key => scheme)
29
29
  self.scheme = scheme
30
30
 
31
31
  instance_exec(&block) if block_given?
@@ -39,13 +39,15 @@ module MediaTypes
39
39
  # @return [Scheme] the scheme for the given +media_type+
40
40
  #
41
41
  def find(media_type, default = -> { Scheme.new(allow_empty: true) { not_strict } })
42
- registry.fetch(String(media_type)) do
42
+ registry.fetch(media_type.as_key) do
43
43
  default.call
44
44
  end
45
45
  end
46
46
 
47
47
  def method_missing(method_name, *arguments, &block)
48
48
  if scheme.respond_to?(method_name)
49
+ media_type.__getobj__.media_type_combinations.add(media_type.as_key)
50
+
49
51
  return scheme.send(method_name, *arguments, &block)
50
52
  end
51
53
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MediaTypes
4
- VERSION = '0.6.2'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -31,6 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency 'minitest-ci'
32
32
  spec.add_development_dependency 'minitest-reporters'
33
33
  spec.add_development_dependency 'oj'
34
- spec.add_development_dependency 'rake', '~> 12.3'
34
+ spec.add_development_dependency 'rake', '~> 13.0'
35
35
  spec.add_development_dependency 'simplecov'
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: media_types
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derk-Jan Karrenbeld
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-10 00:00:00.000000000 Z
11
+ date: 2020-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '12.3'
131
+ version: '13.0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '12.3'
138
+ version: '13.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: simplecov
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -158,6 +158,7 @@ executables: []
158
158
  extensions: []
159
159
  extra_rdoc_files: []
160
160
  files:
161
+ - ".github/workflows/ruby.yml"
161
162
  - ".gitignore"
162
163
  - ".rubocop.yml"
163
164
  - ".travis.yml"
@@ -169,6 +170,7 @@ files:
169
170
  - bin/console
170
171
  - bin/setup
171
172
  - lib/media_types.rb
173
+ - lib/media_types/.dsl.rb.swp
172
174
  - lib/media_types/constructable.rb
173
175
  - lib/media_types/defaults.rb
174
176
  - lib/media_types/dsl.rb