Skip to content

Commit

Permalink
Merge pull request #147 from SleeplessByte/feature/automatic-index-co…
Browse files Browse the repository at this point in the history
…llection

Add helper methods for use with serialization
  • Loading branch information
SleeplessByte authored Aug 7, 2023
2 parents f98dfd7 + 15d83fb commit fff4649
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 17 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@
.idea/

/media_types-*.gem
/media-types-*.tar.gz
/ruby-media-types-*
/ruby-media-types_*.deb
/ruby-media-types_*.buildinfo
/ruby-media-types_*.changes
/ruby-media-types_*.debian.tar.xz
/ruby-media-types_*.dsc
/ruby-media-types_*.orig.tar.gz
25 changes: 13 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
## 2.2.0

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

## 2.1.1

Expand All @@ -23,25 +24,25 @@

## 2.0.0

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

## 1.0.0

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

## 0.6.2

Expand Down
6 changes: 6 additions & 0 deletions lib/media_types/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@ def initialize(mod:)
super(format('Unable to change key type expectation for %<mod>s since its current expectation is already used', mod: mod.name))
end
end

class CollectionDefinitionNotFound < StandardError
def initialize(current, target)
super(format('Unable to use %<target>s as a collection inside %<current>s, no such schema has been defined.', current: current, target: target))
end
end
end
end
29 changes: 25 additions & 4 deletions lib/media_types/scheme.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ class Scheme
#
# @see MissingValidation
#
def initialize(allow_empty: false, expected_type: ::Object, &block)
def initialize(allow_empty: false, expected_type: ::Object, current_type: nil, registry: nil, &block)
self.rules = Rules.new(allow_empty: allow_empty, expected_type: expected_type)
self.type_attributes = {}
self.fixtures = []
self.asserted_sane = false
@registry = registry
@current_type = current_type

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

rules.default = Scheme.new(allow_empty: allow_empty, expected_type: expected_type, &block)
rules.default = Scheme.new(allow_empty: allow_empty, expected_type: expected_type, registry: @registry, current_type: @current_type, &block)
end

##
Expand Down Expand Up @@ -348,10 +350,20 @@ def not_strict
# MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
# # => true
#
def collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, optional: false, &block)
def collection(key, scheme = nil, view: nil, allow_empty: false, expected_type: ::Array, optional: false, &block)
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?

unless block_given?
if scheme.nil?
dependent_key = @current_type.as_key.dup
dependent_key[1] = view

unless @registry.has_key? dependent_key
raise Errors::CollectionDefinitionNotFound.new(@current_type.override_suffix('json').to_s, @current_type.view(view).override_suffix('json').to_s)
end
scheme = @registry[dependent_key]
end

return rules.add(
key,
EnumerationOfType.new(
Expand All @@ -363,7 +375,16 @@ def collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, op
)
end

rules.add(key, Scheme.new(allow_empty: allow_empty, expected_type: expected_type, &block), optional: optional)
rules.add(key, Scheme.new(allow_empty: allow_empty, expected_type: expected_type, registry: @registry, current_type: @current_type, &block), optional: optional)
end

##
# Expect an index of links
#
def index(optional: false)
collection(:_links, optional: optional) do
link :_self
end
end

##
Expand Down
2 changes: 1 addition & 1 deletion lib/media_types/validations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Validations
# @see Constructable
# @see Scheme
#
def initialize(media_type, registry = {}, scheme = Scheme.new, &block)
def initialize(media_type, registry = {}, scheme = Scheme.new(registry: registry, current_type: media_type), &block)
self.media_type = media_type
self.registry = registry.merge!(media_type.as_key => scheme)
self.scheme = scheme
Expand Down
27 changes: 27 additions & 0 deletions test/media_types/dsl/collection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,33 @@ def self.organisation
end
end


class IndexCollectionType
include MediaTypes::Dsl

def self.organisation
'acme'
end

use_name 'index_test'

validations do
version 1 do
attribute :bar, Numeric
end

view :index do
version 1 do
collection :_embedded
end
end
end
end

def test_index_collections
assert IndexCollectionType.view(:index).version(1).validate!({ _embedded: [{ bar: 42 }] }), 'Expected input to be valid'
end

end
end
end

0 comments on commit fff4649

Please sign in to comment.