media_types 2.2.0 → 2.3.2

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: 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"