Skip to content

Commit fff4649

Browse files
Merge pull request #147 from SleeplessByte/feature/automatic-index-collection
Add helper methods for use with serialization
2 parents f98dfd7 + 15d83fb commit fff4649

File tree

6 files changed

+80
-17
lines changed

6 files changed

+80
-17
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,11 @@
1010
.idea/
1111

1212
/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

CHANGELOG.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
## 2.2.0
44

55
- Add ability to define multiple versions using one block.
6+
- Add `index` attribute type that automatically generates a link list compatible with media_types-serialization.
7+
- Add support for `collection` to automatically look up a previously defined schema when passing a view.
68
- Add ability to mark certain attributes as optional when validating with `loose: true` and required otherwise.
7-
- Add ability to define multiple versions using one block
89

910
## 2.1.1
1011

@@ -23,25 +24,25 @@
2324

2425
## 2.0.0
2526

26-
- Removed ability to set default suffix. All suffixes now default to `+json`.
27+
- Remove ability to set default suffix. All suffixes now default to `+json`.
2728
- Suffixes are now set for a given view and version instead of as a block.
28-
- Added `suffix :yoursuffix` command to override the default `:json` suffix.
29-
- Removed defaults block.
30-
- Removed registrations block.
29+
- Add `suffix :yoursuffix` command to override the default `:json` suffix.
30+
- Remove defaults block.
31+
- Remove registrations block.
3132

3233
## 1.0.0
3334

34-
- Added the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
35+
- Add the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
3536
- `media_type` has been replaced with `use_name`.
3637
- It is no longer possible to set a default version. Please use `version <x> do` instead.
3738
- 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.
3839
- `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
39-
- Added the `empty` validation to mark an empty object as valid.
40-
- Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
41-
- Added `version(x)` and `view(x)` functions.
42-
- Added an `available_validations` functions that returns all defined validations.
43-
- Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
44-
- Fixed an issue where undefined validations would accept an empty object.
40+
- Add the `empty` validation to mark an empty object as valid.
41+
- Add the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
42+
- Add `version(x)` and `view(x)` functions.
43+
- Add an `available_validations` functions that returns all defined validations.
44+
- Fix an issue where validations could accidentally merge if defined with a bad `base_format`.
45+
- Fix an issue where undefined validations would accept an empty object.
4546

4647
## 0.6.2
4748

lib/media_types/errors.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,11 @@ def initialize(mod:)
1515
super(format('Unable to change key type expectation for %<mod>s since its current expectation is already used', mod: mod.name))
1616
end
1717
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
1824
end
1925
end

lib/media_types/scheme.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ class Scheme
9494
#
9595
# @see MissingValidation
9696
#
97-
def initialize(allow_empty: false, expected_type: ::Object, &block)
97+
def initialize(allow_empty: false, expected_type: ::Object, current_type: nil, registry: nil, &block)
9898
self.rules = Rules.new(allow_empty: allow_empty, expected_type: expected_type)
9999
self.type_attributes = {}
100100
self.fixtures = []
101101
self.asserted_sane = false
102+
@registry = registry
103+
@current_type = current_type
102104

103105
instance_exec(&block) if block_given?
104106
end
@@ -270,7 +272,7 @@ def any(scheme = nil, expected_type: ::Hash, allow_empty: false, &block)
270272
return rules.default = Attribute.new(scheme)
271273
end
272274

273-
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)
274276
end
275277

276278
##
@@ -348,10 +350,20 @@ def not_strict
348350
# MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
349351
# # => true
350352
#
351-
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)
352354
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?
353355

354356
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+
355367
return rules.add(
356368
key,
357369
EnumerationOfType.new(
@@ -363,7 +375,16 @@ def collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, op
363375
)
364376
end
365377

366-
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
367388
end
368389

369390
##

lib/media_types/validations.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Validations
2525
# @see Constructable
2626
# @see Scheme
2727
#
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)
2929
self.media_type = media_type
3030
self.registry = registry.merge!(media_type.as_key => scheme)
3131
self.scheme = scheme

test/media_types/dsl/collection_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,33 @@ def self.organisation
305305
end
306306
end
307307

308+
309+
class IndexCollectionType
310+
include MediaTypes::Dsl
311+
312+
def self.organisation
313+
'acme'
314+
end
315+
316+
use_name 'index_test'
317+
318+
validations do
319+
version 1 do
320+
attribute :bar, Numeric
321+
end
322+
323+
view :index do
324+
version 1 do
325+
collection :_embedded
326+
end
327+
end
328+
end
329+
end
330+
331+
def test_index_collections
332+
assert IndexCollectionType.view(:index).version(1).validate!({ _embedded: [{ bar: 42 }] }), 'Expected input to be valid'
333+
end
334+
308335
end
309336
end
310337
end

0 commit comments

Comments
 (0)