MediaTypes::Deserialization
Add media types supported deserialization using your favourite deserializer, and (when supported and provided) media type validation.
Installation
Add this line to your application's Gemfile:
gem 'media_types-deserialization'
And then execute:
$ bundle
Or install it yourself as:
$ gem install media_types-deserialization
Usage
All logic lives in the MediaTypes::Deserialization
and the main method you'll use is media_type_params
. This works
very similarly as params
in Rack
(and therefore Rails
) applications, but only gives back what the implicit or
explicit deserializer gives back.
require 'media_types/deserialization'
class BaseController
include MediaTypes::Deserialization
rescue_from ContentFormatError, with: :bad_request # 400
rescue_from ContentTypeNotRecognised, with: :unsupported_media_type # 415
rescue_from ContentDoesNotMatchContentType, with: :unprocessable_entity # 422
end
Content Type lookup (symbol)
If you don't provide the lookup_content_type_symbol
configuration, it requires 'action_dispatch/http/mime_type'
to
be present in order to look-up the content type symbol. This is true for Rails
applications by default.
MediaTypes::Deserialization.configure do
self.lookup_content_type_symbol = lambda do |content_type|
# For example use a lookup map
KNOWN_CONTENT_TYPES_TO_SYMBOL[content_type]
# Or alternatively use matching
content_type.include?('json') ? :json : nil
end
end
See below if you're using the media_types
gem.
Deserializer lookup
If you don't provide the lookup_deserializer_by_symbol
configuration, it currently can only deserialize json
and
will only do so if the symbol is :json
, requiring oj
. If you don't want this behaviour, define it.
MediaTypes::Deserialization.configure do
self.lookup_deserializer_by_symbol = lambda do |symbol|
case symbol
when :json
return CustomJsonDeserializer
when :xml
when :html
when :xhtml
return CustomXmlDeserializer
else
nil
end
end
end
Media Type lookup and validation
If you want media type validation, for example via the media_types
gem, provide the lookup_media_type_by_symbol
option and return the media types. The easiest way to accomplish this is tracking your registerables when you register
the media types, and creating a Lookup Map like so:
# In some initializer that defines the media types,
# given a module MyDomain::MediaTypes which holds many media types
require 'my_domain/media_types'
require 'media_types/integrations/actionpack'
registerables = []
MyDomain::MediaTypes.module_exec do
registerables.concat self::Author.register
registerables.concat self::Book.register
registerables.concat self::Configuration.register
registerables.concat self::Errors.register
registerables.concat self::Signature.register
# Create lookup table by string (content-type) => media type
lookup = registerables.flatten.each_with_object({}) do |registerable, hash|
[registerable.media_type, *registerable.aliases].each do |type|
hash[String(type)] = registerable
end
end.freeze
# Create lookup table by symbol => media_type
lookup_by_symbol = registerables.flatten.each_with_object({}) do |registerable, hash|
hash[String(registerable.symbol).to_sym] = registerable
end.freeze
const_set(:LOOKUP, lookup)
const_set(:LOOKUP_BY_SYMBOL, lookup_by_symbol)
end
At this point you can re-use those lookup tables for both the media type lookup and the symbol lookup:
MediaTypes::Deserialization.configure do
self.lookup_content_type_symbol = lambda do |content_type|
registerable = MyDomain::MediaTypes.const_get(:Lookup).fetch(content_type) { nil }
registerable&.symbol
end
self.lookup_media_type_by_symbol = lambda do |symbol|
registerable = MyDomain::MediaTypes.const_get(:LOOKUP_BY_SYMBOL).fetch(symbol) { nil }
registerable&.media_type
end
end
Related
MediaTypes
: :gem: Library to create media type definitions, schemes and validationsMediaTypes::Serialization
: :cyclone: Add media types supported serialization using your favourite serializerMediaTypes::Validation
: :heavy_exclamation_mark: Response validations according to a media-type
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can
also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the
version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version,
push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at XPBytes/media_types-deserialization.