Simple solution for serializing you data in hanami apps.
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
]
#send_json
- casts object as json and sets it to actionbody
#serializer
- returns serializer class for current action
# 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
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
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" }'
You can use nested data structures. You have 2 ways how to use it
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
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
You can share your serializer code using general classes. For this you need:
- Create model-specific serializer
- 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
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.
The gem is available as open source under the terms of the MIT License.