Home

Awesome

NOT MAINTAINED

Hanami::Serializer

Simple solution for serializing you data in hanami apps.

Installation

Add this line to your application's Gemfile:

gem 'hanami-serializer'

And then execute:

$ bundle

Or install it yourself as:

$ gem install hanami-serializer

Create 'Types' module:

# lib/types.rb

module Types
  include Dry::Types.module
end

Create and add serializers folder to application:

# apps/api/application.rb

load_paths << %w[
  controllers
  serializers
]

Usage

Action helpers

Example

# api/controllers/controller/index.rb

module Api::Controllers::Controller
  class Show
    include Api::Action
    include Hanami::Serializer::Action

    def call(params)
      object = repo.find(params[:id])

      serializer # => Api::Serializers::Controller::Show

      object = serializer.new(object)
      send_json(object)

      # simular to
      #
      #   self.status = 200
      #   self.body = JSON.generate(object)
    end
  end
end

Custom serializer class

If you want to use custom serializer class you can override #serializer method like this:

# api/controllers/controller/index.rb

module Api::Controllers::Controller
  class Update
    include Api::Action
    include Hanami::Serializer::Action

    def call(params)
      serializer # => Api::Serializers::Controller::Create

      # code
    end

    def serializer
      @serializer ||= Api::Serializers::Controller::Create
    end
  end
end

Serializers

Create simple serializer for each action:

# api/serializers/controller/index.rb

module Api::Serializers
  module Controller
    class Show < Hanami::Serializer::Base
      # put here attributes needful for action
      attribute :id,   Types::Id
      attribute :name, Types::UserName
    end
  end
end

And after that you can use it like a usual ruby object:

user = User.new(id: 1, name: 'anton', login: 'davydovanton')

serializer = Api::Serializers::Contributors::Index.new(user)

serializer.to_json        # => '{ "id":1, "name": "anton" }'
serializer.call           # => '{ "id":1, "name": "anton" }'
JSON.generate(serializer) # => '{ "id":1, "name": "anton" }'

Nested

You can use nested data structures. You have 2 ways how to use it

Type

We can create new hash type of attribute:

class UserWithAvatarSerializer < Hanami::Serializer::Base
  attribute :name, Types::String

  attribute :avatar, Types::Hash.schema(
    upload_file_name: Types::String,
    upload_file_size: Types::Coercible::Int
  )
end

Serializer

We can user other serializer as a type for attribute:

class AvatarSerializer < Hanami::Serializer::Base
  attribute :upload_file_name, Types::String
  attribute :upload_file_size, Types::Coercible::Int
end

class NestedUserSerializer < Hanami::Serializer::Base
  attribute :name, Types::String
  attribute :avatar, AvatarSerializer
end

Shared

You can share your serializer code using general classes. For this you need:

  1. Create model-specific serializer
  2. Use oop inheritance for sharing model-specific attributes
# api/serializers/user.rb

module Api::Serializers
  class User < Hanami::Serializer::Base
    attribute :name, Types::UserName
  end
end
# api/serializers/users/index.rb
module Api::Serializers
  module Users
    class Index < User
      # put here other attributes needful for action
      attribute :id, Types::Id
    end
  end
end

# api/serializers/users/show.rb
module Api::Serializers
  module Users
    class Show < User
      # put here other attributes needful for action
      attribute :posts, Types::Posts
    end
  end
end

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/davydovanton/hanami-serializer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.