Skip to content
🌀 Add media types supported deserialization using your favourite parser, and media type validation.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.idea
bin
lib/media_types
test
.gitignore
.travis.yml
CHANGELOG.md
CODE_OF_CONDUCT.md
Gemfile
Gemfile.lock
LICENSE.txt
README.md
Rakefile
media_types-deserialization.gemspec

README.md

MediaTypes::Deserialization

Build Status: master Gem Version MIT license

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

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.

You can’t perform that action at this time.