media_types 2.2.0 → 2.3.2

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: 60066d3701955c4cd09e1aebea4c444e7bda6f046119fdf535af562757e50b42
4
- data.tar.gz: 54dec80cb8d9b53a1b7dfcb0269f3d6688b06cf48050f74a93f50a91169ac8cc
3
+ metadata.gz: 1142ee3380c374e5f49563e0bc5dd52d379b1d5f0971f32573d1c4e508da8a53
4
+ data.tar.gz: 1110579b304aeaaa2cdf1c78c9083df5dae0c42a903daf448c5f8c3abea77c41
5
5
  SHA512:
6
- metadata.gz: 9d75689e60008e8b728082181b81eed52d68fab6709b3588729cec9f257b7aca045dd8739ab2c888dc03730900f530fc1e6cf3f87544964be6028c0a177db4f3
7
- data.tar.gz: cfe50c15068b984cf1f7576fdfb8cc70c2e4486ebb4be7594704160017534288b0c09dd8f59703fcc6b5b98b7068b34daa235185beefab8bc3394df0984d4f60
6
+ metadata.gz: 9c91d590c74715eaf9d5cc705f9fc8cc1c8777fd32aaabd0a155548dc04c1c22426a5cd387803116956d8665465ec9ff5bee8c3f81140acb649e3a74821c449f
7
+ data.tar.gz: 520d8fa98570b498aaeae73168ea6e2c286fa918936874030eb16d42901e81a4431c10c2af168594f33c01e677f00ce46f2d7b9bd993051aaa634231ab70bf61
@@ -11,7 +11,7 @@ jobs:
11
11
  steps:
12
12
  - uses: actions/checkout@v1
13
13
  - name: Set up Ruby 2.7 (debian ruby)
14
- uses: ruby/setup-ruby@v2
14
+ uses: ruby/setup-ruby@v1
15
15
  with:
16
16
  ruby-version: 2.7
17
17
  - name: Install dependencies
@@ -0,0 +1,34 @@
1
+ name: Publish debian bookworm packages
2
+
3
+ on:
4
+ - workflow_dispatch
5
+
6
+ jobs:
7
+ publish-bookworm:
8
+ runs-on: ubuntu-latest
9
+ container:
10
+ image: debian:bookworm
11
+ steps:
12
+ - name: Install repo
13
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install wget && wget -O key.deb https://deb1.ws.maxmaton.nl/key.deb && DEBIAN_FRONTEND=noninteractive apt-get --yes install ./key.deb && echo "deb [signed-by=/usr/share/keyrings/maxmaton.gpg] http://deb.maxmaton.nl/debian bookworm main non-free" > /etc/apt/sources.list.d/maxmaton.list
14
+ - name: Install dependencies
15
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install git build-essential gem scrypt sshpass gem2deb ruby-actionpack ruby-activesupport
16
+ - uses: actions/checkout@v3
17
+ name: Check out repository
18
+ - name: Build gem
19
+ run: |
20
+ git config --global --add safe.directory "$(pwd)"
21
+ sed -i -re "s/VERSION\s+=\s+'([0-9]+.[0-9]+.[0-9]+)'/VERSION = '\1.bookworm'/g" lib/media_types/version.rb
22
+ gem build media_types.gemspec
23
+ - name: Build deb
24
+ run: DEBEMAIL=info@delftsolutions.nl gem2deb media_types-*.gem && ls -hal
25
+ - name: Publish
26
+ env:
27
+ PUBLISH_SIGNING_KEY: ${{ secrets.PUBLISH_SIGNING_KEY }}
28
+ SSHPASS: ${{ secrets.SSHPASS }}
29
+ run: |
30
+ echo "deb1.ws.maxmaton.nl ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgN3TiyKvRTj4xBSyQtYz0OuHZYv2i+x3NL+svh2k0SgPr0Xms4Vu+g3AXntXUQGRM0W9zbcZSHiBIWbliv3Y+20f7lKlj9uXUEMHDuiB7Fu7dXObfHswIvTX3XWiPdDeG1jYQbGM3tENX/wtEoixyL++33O69t2SFR5MkPk+/j+zlGLCFf0ypTAMb7bT5NjRNM3+v0LT2WVSZuawA7Fl8WBVTq7MSSuCZIxHIv1kEq6AWpOjWZHNVZrijs+uRTIPcrZ47wSt6tanjAnWT9sAzu8KqcvQsPw9IQwqV1nfQWz0wMit7ijn9B3MrkNHXP5PaNiZQCezsbrh9glhShz0z" > known_hosts
31
+ echo "deb1.ws.maxmaton.nl ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMr5uAraiRj0pQ9Q9dQO0xMosTzFUAe+VjtMclIUbdJ7r7XMUa3etxh3BfBlW4nq3ZdIFCsV2zwzTaYSmfh95Xs=" >> known_hosts
32
+ echo "deb1.ws.maxmaton.nl ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPhQl7Ik6h7hSQbdo9ZfF78WYFCzch8SAOXFBxxAZH06" >> known_hosts
33
+ echo "Uploading :" ruby-media-types_*.deb
34
+ scrypt enc --passphrase "env:PUBLISH_SIGNING_KEY" ruby-media-types_*.deb | sshpass -e ssh -o "UserKnownHostsFile=known_hosts" publish@deb1.ws.maxmaton.nl "echo 'uploading bookworm' && sudo /opt/max/publish-deb ruby-media-types bookworm main && echo 'bookworm done'"
@@ -0,0 +1,34 @@
1
+ name: Publish debian sid packages
2
+
3
+ on:
4
+ - workflow_dispatch
5
+
6
+ jobs:
7
+ publish-sid:
8
+ runs-on: ubuntu-latest
9
+ container:
10
+ image: debian:sid
11
+ steps:
12
+ - name: Install repo
13
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install wget && wget -O key.deb https://deb1.ws.maxmaton.nl/key.deb && DEBIAN_FRONTEND=noninteractive apt-get --yes install ./key.deb && echo "deb [signed-by=/usr/share/keyrings/maxmaton.gpg] http://deb.maxmaton.nl/debian sid main non-free" > /etc/apt/sources.list.d/maxmaton.list
14
+ - name: Install dependencies
15
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install git build-essential gem scrypt sshpass gem2deb ruby-actionpack ruby-activesupport
16
+ - uses: actions/checkout@v3
17
+ name: Check out repository
18
+ - name: Build gem
19
+ run: |
20
+ git config --global --add safe.directory "$(pwd)"
21
+ sed -i -re "s/VERSION\s+=\s+'([0-9]+.[0-9]+.[0-9]+)'/VERSION = '\1.sid'/g" lib/media_types/version.rb
22
+ gem build media_types.gemspec
23
+ - name: Build deb
24
+ run: DEBEMAIL=info@delftsolutions.nl gem2deb media_types-*.gem && ls -hal
25
+ - name: Publish
26
+ env:
27
+ PUBLISH_SIGNING_KEY: ${{ secrets.PUBLISH_SIGNING_KEY }}
28
+ SSHPASS: ${{ secrets.SSHPASS }}
29
+ run: |
30
+ echo "deb1.ws.maxmaton.nl ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgN3TiyKvRTj4xBSyQtYz0OuHZYv2i+x3NL+svh2k0SgPr0Xms4Vu+g3AXntXUQGRM0W9zbcZSHiBIWbliv3Y+20f7lKlj9uXUEMHDuiB7Fu7dXObfHswIvTX3XWiPdDeG1jYQbGM3tENX/wtEoixyL++33O69t2SFR5MkPk+/j+zlGLCFf0ypTAMb7bT5NjRNM3+v0LT2WVSZuawA7Fl8WBVTq7MSSuCZIxHIv1kEq6AWpOjWZHNVZrijs+uRTIPcrZ47wSt6tanjAnWT9sAzu8KqcvQsPw9IQwqV1nfQWz0wMit7ijn9B3MrkNHXP5PaNiZQCezsbrh9glhShz0z" > known_hosts
31
+ echo "deb1.ws.maxmaton.nl ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMr5uAraiRj0pQ9Q9dQO0xMosTzFUAe+VjtMclIUbdJ7r7XMUa3etxh3BfBlW4nq3ZdIFCsV2zwzTaYSmfh95Xs=" >> known_hosts
32
+ echo "deb1.ws.maxmaton.nl ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPhQl7Ik6h7hSQbdo9ZfF78WYFCzch8SAOXFBxxAZH06" >> known_hosts
33
+ echo "Uploading :" ruby-media-types_*.deb
34
+ scrypt enc --passphrase "env:PUBLISH_SIGNING_KEY" ruby-media-types_*.deb | sshpass -e ssh -o "UserKnownHostsFile=known_hosts" publish@deb1.ws.maxmaton.nl "echo 'uploading sid' && sudo /opt/max/publish-deb ruby-media-types sid main && echo 'sid done'"
data/.gitignore CHANGED
@@ -8,3 +8,13 @@
8
8
  /tmp/
9
9
 
10
10
  .idea/
11
+
12
+ /media_types-*.gem
13
+ /media-types-*.tar.gz
14
+ /ruby-media-types-*
15
+ /ruby-media-types_*.deb
16
+ /ruby-media-types_*.buildinfo
17
+ /ruby-media-types_*.changes
18
+ /ruby-media-types_*.debian.tar.xz
19
+ /ruby-media-types_*.dsc
20
+ /ruby-media-types_*.orig.tar.gz
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.2
4
+
5
+ - Fix that causes bailout in nested rule to stop validation altogether
6
+
7
+ ## 2.3.1
8
+
9
+ - Fix build issue that caused debian package to be empty
10
+
11
+ ## 2.3.0
12
+
13
+ - Add ability to define multiple versions using one block.
14
+ - Add `index` attribute type that automatically generates a link list compatible with media_types-serialization.
15
+ - Add support for `collection` to automatically look up a previously defined schema when passing a view.
16
+ - Add ability to mark certain attributes as optional when validating with `loose: true` and required otherwise.
17
+
18
+ ## 2.2.0
19
+
20
+ - Change dependencies and build output to be debian compatible
21
+
3
22
  ## 2.1.1
4
23
 
5
24
  - Fix Ruby 2.6 to 2.7 incompatible change
@@ -17,25 +36,25 @@
17
36
 
18
37
  ## 2.0.0
19
38
 
20
- - Removed ability to set default suffix. All suffixes now default to `+json`.
39
+ - Remove ability to set default suffix. All suffixes now default to `+json`.
21
40
  - Suffixes are now set for a given view and version instead of as a block.
22
- - Added `suffix :yoursuffix` command to override the default `:json` suffix.
23
- - Removed defaults block.
24
- - Removed registrations block.
41
+ - Add `suffix :yoursuffix` command to override the default `:json` suffix.
42
+ - Remove defaults block.
43
+ - Remove registrations block.
25
44
 
26
45
  ## 1.0.0
27
46
 
28
- - Added the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
47
+ - Add the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
29
48
  - `media_type` has been replaced with `use_name`.
30
49
  - It is no longer possible to set a default version. Please use `version <x> do` instead.
31
50
  - 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.
32
51
  - `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
33
- - Added the `empty` validation to mark an empty object as valid.
34
- - Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
35
- - Added `version(x)` and `view(x)` functions.
36
- - Added an `available_validations` functions that returns all defined validations.
37
- - Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
38
- - Fixed an issue where undefined validations would accept an empty object.
52
+ - Add the `empty` validation to mark an empty object as valid.
53
+ - Add the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
54
+ - Add `version(x)` and `view(x)` functions.
55
+ - Add an `available_validations` functions that returns all defined validations.
56
+ - Fix an issue where validations could accidentally merge if defined with a bad `base_format`.
57
+ - Fix an issue where undefined validations would accept an empty object.
39
58
 
40
59
  ## 0.6.2
41
60
 
data/Gemfile.lock CHANGED
@@ -1,43 +1,43 @@
1
- PATH
2
- remote: .
3
- specs:
4
- media_types (2.1.1)
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.18.0)
14
- minitest-reporters (1.6.0)
15
- ansi
16
- builder
17
- minitest (>= 5.0)
18
- ruby-progressbar
19
- oj (3.14.2)
20
- rake (13.0.6)
21
- ruby-progressbar (1.13.0)
22
- simplecov (0.22.0)
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.4)
28
-
29
- PLATFORMS
30
- x64-mingw32
31
-
32
- DEPENDENCIES
33
- awesome_print
34
- bundler (>= 2)
35
- media_types!
36
- minitest
37
- minitest-reporters
38
- oj
39
- rake
40
- simplecov
41
-
42
- BUNDLED WITH
43
- 2.1.4
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ media_types (2.3.2)
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.18.0)
14
+ minitest-reporters (1.6.0)
15
+ ansi
16
+ builder
17
+ minitest (>= 5.0)
18
+ ruby-progressbar
19
+ oj (3.14.2)
20
+ rake (13.0.6)
21
+ ruby-progressbar (1.13.0)
22
+ simplecov (0.22.0)
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.4)
28
+
29
+ PLATFORMS
30
+ x64-mingw32
31
+
32
+ DEPENDENCIES
33
+ awesome_print
34
+ bundler (>= 2)
35
+ media_types!
36
+ minitest
37
+ minitest-reporters
38
+ oj
39
+ rake
40
+ simplecov
41
+
42
+ BUNDLED WITH
43
+ 2.1.4
data/README.md CHANGED
@@ -81,7 +81,7 @@ class Venue
81
81
 
82
82
  version 1 do
83
83
  attribute :name, String
84
- attribute :coords, String
84
+ attribute :coords, String, optional: :loose
85
85
  attribute :updated_at, String
86
86
 
87
87
  link :self
@@ -94,8 +94,10 @@ class Venue
94
94
  attribute :altitude, AllowNil(Numeric)
95
95
  end
96
96
 
97
- version 1 do
97
+ versions [1, 2] do |v|
98
98
  collection :location do
99
+ link :extra if v > 1
100
+
99
101
  attribute :latitude, Numeric
100
102
  attribute :longitude, Numeric
101
103
  attribute :altitude, AllowNil(Numeric)
@@ -465,8 +467,8 @@ class MyMedia
465
467
  { "foo": { "bar": "string" } }
466
468
  FIXTURE
467
469
  assert_fail '{"foo": {}}'
468
- assert_fail '{"foo": null}'
469
- assert_fail '{"foo": [42]}'
470
+ assert_fail '{"foo": null}', loose: true
471
+ assert_fail '{"foo": [42]}', loose: false
470
472
  end
471
473
  end
472
474
 
@@ -125,6 +125,7 @@ module MediaTypes
125
125
  end
126
126
 
127
127
  def validatable?
128
+ return false if media_type_combinations.nil?
128
129
  return false unless media_type_combinations.include? as_key
129
130
 
130
131
  __getobj__.validatable?(self)
@@ -15,5 +15,11 @@ module MediaTypes
15
15
  super(format('Unable to change key type expectation for %<mod>s since its current expectation is already used', mod: mod.name))
16
16
  end
17
17
  end
18
+
19
+ class CollectionDefinitionNotFound < StandardError
20
+ def initialize(current, target)
21
+ super(format('Unable to use %<target>s as a collection inside %<current>s, no such schema has been defined.', current: current, target: target))
22
+ end
23
+ end
18
24
  end
19
25
  end
@@ -29,15 +29,15 @@ module MediaTypes
29
29
  attr_accessor :output, :options, :rules
30
30
 
31
31
  def allow_empty?
32
- rules.allow_empty? || rules.required.empty?
32
+ rules.allow_empty? || rules.required(loose: options.loose).empty?
33
33
  end
34
34
 
35
35
  def raise_empty!(backtrace:, found:)
36
36
  raise EmptyOutputError, format(
37
- 'Expected output, got empty at %<backtrace>s. Required are: %<required>s. Found: %<found>s',
37
+ 'The object at %<backtrace>s was empty but I expected contents. Required keys are: %<required>s.',
38
38
  backtrace: backtrace.join('->'),
39
- required: rules.required.keys,
40
- found: (found.is_a? Hash) ? found.keys : found.class.name,
39
+ required: rules.required(loose: options.loose).keys,
40
+ found: (found.respond_to? :keys) ? found.keys : found.class.name,
41
41
  )
42
42
  end
43
43
  end
@@ -14,6 +14,7 @@ module MediaTypes
14
14
  self.allow_empty = allow_empty
15
15
  self.expected_type = expected_type
16
16
  self.optional_keys = []
17
+ self.strict_keys = []
17
18
  self.original_key_type = {}
18
19
 
19
20
  self.default = MissingValidation.new
@@ -32,7 +33,11 @@ module MediaTypes
32
33
 
33
34
  normalized_key = normalize_key(key)
34
35
  __getobj__[normalized_key] = val
35
- optional_keys << normalized_key if optional
36
+ if optional == :loose
37
+ strict_keys << normalized_key
38
+ else
39
+ optional_keys << normalized_key if optional
40
+ end
36
41
  original_key_type[normalized_key] = key.class
37
42
 
38
43
  self
@@ -87,11 +92,16 @@ module MediaTypes
87
92
  #
88
93
  # @return [Array<Symbol>] required keys
89
94
  #
90
- def required
95
+ def required(loose:)
91
96
  clone.tap do |cloned|
92
97
  optional_keys.each do |key|
93
98
  cloned.delete(key)
94
99
  end
100
+ if loose
101
+ strict_keys.each do |key|
102
+ cloned.delete(key)
103
+ end
104
+ end
95
105
  end
96
106
  end
97
107
 
@@ -113,6 +123,9 @@ module MediaTypes
113
123
  if rules.respond_to?(:optional_keys, true)
114
124
  optional_keys.push(*rules.send(:optional_keys))
115
125
  end
126
+ if rules.respond_to?(:strict_keys, true)
127
+ strict_keys.push(*rules.send(:strict_keys))
128
+ end
116
129
 
117
130
  self
118
131
  end
@@ -123,7 +136,7 @@ module MediaTypes
123
136
  return "#{prefix}[Error]Depth limit reached[/Error]" if indent > 5_000
124
137
 
125
138
  [
126
- "#{prefix}[Rules n=#{keys.length} optional=#{optional_keys.length} allow_empty=#{allow_empty?}]",
139
+ "#{prefix}[Rules n=#{keys.length} optional=#{optional_keys.length} strict=#{strict_keys.length} allow_empty=#{allow_empty?}]",
127
140
  "#{prefix} #{inspect_format_attribute(indent, '*', default)}",
128
141
  *keys.map { |key| "#{prefix} #{inspect_format_attribute(indent, key)}" },
129
142
  "#{prefix}[/Rules]"
@@ -162,7 +175,7 @@ module MediaTypes
162
175
 
163
176
  private
164
177
 
165
- attr_accessor :allow_empty, :optional_keys, :original_key_type
178
+ attr_accessor :allow_empty, :strict_keys, :optional_keys, :original_key_type
166
179
  attr_writer :expected_type
167
180
 
168
181
  def normalize_key(key)
@@ -26,7 +26,7 @@ module MediaTypes
26
26
  return iterate(EMPTY_MARK)
27
27
  end
28
28
 
29
- required_rules = rules.required
29
+ required_rules = rules.required(loose: options.loose)
30
30
  # noinspection RubyScope
31
31
  result = iterate(->(key) { required_rules.remove(key) })
32
32
  return result if required_rules.empty?
@@ -48,11 +48,13 @@ module MediaTypes
48
48
 
49
49
  mark.call(key)
50
50
 
51
- rules.get(key).validate!(
52
- value,
53
- options.trace(key),
54
- context: context
55
- )
51
+ catch(:end) do
52
+ rules.get(key).validate!(
53
+ value,
54
+ options.trace(key),
55
+ context: context
56
+ )
57
+ end
56
58
  end
57
59
  end
58
60
 
@@ -3,18 +3,19 @@
3
3
  module MediaTypes
4
4
  class Scheme
5
5
  class ValidationOptions
6
- attr_accessor :exhaustive, :strict, :backtrace, :context, :expected_key_type
6
+ attr_accessor :exhaustive, :strict, :backtrace, :context, :expected_key_type, :loose
7
7
 
8
- def initialize(context = {}, exhaustive: true, strict: true, backtrace: [], expected_key_type:)
8
+ def initialize(context = {}, exhaustive: true, strict: true, backtrace: [], loose: false, expected_key_type:)
9
9
  self.exhaustive = exhaustive
10
10
  self.strict = strict
11
11
  self.backtrace = backtrace
12
12
  self.context = context
13
13
  self.expected_key_type = expected_key_type
14
+ self.loose = loose
14
15
  end
15
16
 
16
17
  def inspect
17
- "backtrack: #{backtrace.inspect}, strict: #{strict.inspect}, exhaustive: #{exhaustive}, current_obj: #{scoped_output.to_json}"
18
+ "backtrack: #{backtrace.inspect}, strict: #{strict.inspect}, loose: #{loose}, exhaustive: #{exhaustive}, current_obj: #{scoped_output.to_json}"
18
19
  end
19
20
 
20
21
  def scoped_output
@@ -28,7 +29,7 @@ module MediaTypes
28
29
  end
29
30
 
30
31
  def with_backtrace(backtrace)
31
- ValidationOptions.new(context, exhaustive: exhaustive, strict: strict, backtrace: backtrace, expected_key_type: expected_key_type)
32
+ ValidationOptions.new(context, exhaustive: exhaustive, strict: strict, backtrace: backtrace, expected_key_type: expected_key_type, loose: loose)
32
33
  end
33
34
 
34
35
  def trace(*traces)
@@ -36,7 +37,7 @@ module MediaTypes
36
37
  end
37
38
 
38
39
  def exhaustive!
39
- ValidationOptions.new(context, exhaustive: true, strict: strict, backtrace: backtrace, expected_key_type: expected_key_type)
40
+ ValidationOptions.new(context, exhaustive: true, strict: strict, backtrace: backtrace, expected_key_type: expected_key_type, loose: loose)
40
41
  end
41
42
  end
42
43
  end
@@ -51,13 +51,14 @@ module MediaTypes
51
51
  end
52
52
 
53
53
  class FixtureData
54
- def initialize(caller:, fixture:, expect_to_pass:)
54
+ def initialize(caller:, fixture:, expect_to_pass:, loose:)
55
55
  self.caller = caller
56
56
  self.fixture = fixture
57
57
  self.expect_to_pass = expect_to_pass
58
+ self.loose = loose
58
59
  end
59
60
 
60
- attr_accessor :caller, :fixture, :expect_to_pass
61
+ attr_accessor :caller, :fixture, :expect_to_pass, :loose
61
62
 
62
63
  alias expect_to_pass? expect_to_pass
63
64
  end
@@ -93,11 +94,13 @@ module MediaTypes
93
94
  #
94
95
  # @see MissingValidation
95
96
  #
96
- def initialize(allow_empty: false, expected_type: ::Object, &block)
97
+ def initialize(allow_empty: false, expected_type: ::Object, current_type: nil, registry: nil, &block)
97
98
  self.rules = Rules.new(allow_empty: allow_empty, expected_type: expected_type)
98
99
  self.type_attributes = {}
99
100
  self.fixtures = []
100
101
  self.asserted_sane = false
102
+ @registry = registry
103
+ @current_type = current_type
101
104
 
102
105
  instance_exec(&block) if block_given?
103
106
  end
@@ -269,7 +272,7 @@ module MediaTypes
269
272
  return rules.default = Attribute.new(scheme)
270
273
  end
271
274
 
272
- rules.default = Scheme.new(allow_empty: allow_empty, expected_type: expected_type, &block)
275
+ rules.default = Scheme.new(allow_empty: allow_empty, expected_type: expected_type, registry: @registry, current_type: @current_type, &block)
273
276
  end
274
277
 
275
278
  ##
@@ -347,10 +350,20 @@ module MediaTypes
347
350
  # MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
348
351
  # # => true
349
352
  #
350
- def collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, optional: false, &block)
353
+ def collection(key, scheme = nil, view: nil, allow_empty: false, expected_type: ::Array, optional: false, &block)
351
354
  raise ConflictingTypeDefinitionError, 'You cannot apply a block to a non-hash typed collection, either remove the type or the block' if scheme != ::Hash && block_given? && !scheme.nil?
352
355
 
353
356
  unless block_given?
357
+ if scheme.nil?
358
+ dependent_key = @current_type.as_key.dup
359
+ dependent_key[1] = view
360
+
361
+ unless @registry.has_key? dependent_key
362
+ raise Errors::CollectionDefinitionNotFound.new(@current_type.override_suffix('json').to_s, @current_type.view(view).override_suffix('json').to_s)
363
+ end
364
+ scheme = @registry[dependent_key]
365
+ end
366
+
354
367
  return rules.add(
355
368
  key,
356
369
  EnumerationOfType.new(
@@ -362,7 +375,16 @@ module MediaTypes
362
375
  )
363
376
  end
364
377
 
365
- rules.add(key, Scheme.new(allow_empty: allow_empty, expected_type: expected_type, &block), optional: optional)
378
+ rules.add(key, Scheme.new(allow_empty: allow_empty, expected_type: expected_type, registry: @registry, current_type: @current_type, &block), optional: optional)
379
+ end
380
+
381
+ ##
382
+ # Expect an index of links
383
+ #
384
+ def index(optional: false)
385
+ collection(:_links, optional: optional) do
386
+ link :_self
387
+ end
366
388
  end
367
389
 
368
390
  ##
@@ -431,14 +453,14 @@ module MediaTypes
431
453
  ].join("\n")
432
454
  end
433
455
 
434
- def assert_pass(fixture)
456
+ def assert_pass(fixture, loose: false)
435
457
  reduced_stack = remove_current_dir_from_stack(caller_locations)
436
- @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: true)
458
+ @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: true, loose: loose)
437
459
  end
438
460
 
439
- def assert_fail(fixture)
461
+ def assert_fail(fixture, loose: false)
440
462
  reduced_stack = remove_current_dir_from_stack(caller_locations)
441
- @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: false)
463
+ @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: false, loose: loose)
442
464
  end
443
465
 
444
466
  # Removes all calls originating in current dir from given stack
@@ -496,7 +518,7 @@ module MediaTypes
496
518
  expected_key_type = expect_symbol_keys ? Symbol : String
497
519
 
498
520
  begin
499
- validate(json, expected_key_type: expected_key_type, backtrace: backtrace)
521
+ validate(json, expected_key_type: expected_key_type, backtrace: backtrace, loose: fixture_data.loose)
500
522
  unless fixture_data.expect_to_pass?
501
523
  raise UnexpectedValidationResultError.new(fixture_data.caller, 'No error encounterd whilst expecting to')
502
524
  end
@@ -25,7 +25,7 @@ module MediaTypes
25
25
  # @see Constructable
26
26
  # @see Scheme
27
27
  #
28
- def initialize(media_type, registry = {}, scheme = Scheme.new, &block)
28
+ def initialize(media_type, registry = {}, scheme = Scheme.new(registry: registry, current_type: media_type), &block)
29
29
  self.media_type = media_type
30
30
  self.registry = registry.merge!(media_type.as_key => scheme)
31
31
  self.scheme = scheme
@@ -89,6 +89,19 @@ module MediaTypes
89
89
  Validations.new(media_type.version(version), registry, &block)
90
90
  end
91
91
 
92
+ ##
93
+ # Runs the block for multiple versions
94
+ #
95
+ # @param [Array] list of versions to run this on
96
+ #
97
+ def versions(versions, &block)
98
+ versions.each do |v|
99
+ Validations.new(media_type.version(v), registry) do
100
+ block(v)
101
+ end
102
+ end
103
+ end
104
+
92
105
  ##
93
106
  # Switches the inner block to a specific view
94
107
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MediaTypes
4
- VERSION = '2.2.0'
4
+ VERSION = '2.3.2'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: media_types
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derk-Jan Karrenbeld
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-03-24 00:00:00.000000000 Z
12
+ date: 2023-08-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: awesome_print
@@ -119,6 +119,8 @@ extensions: []
119
119
  extra_rdoc_files: []
120
120
  files:
121
121
  - ".github/workflows/debian.yml"
122
+ - ".github/workflows/publish-bookworm.yml"
123
+ - ".github/workflows/publish-sid.yml"
122
124
  - ".github/workflows/ruby.yml"
123
125
  - ".gitignore"
124
126
  - ".rubocop.yml"