Curated library of atomic AI agent skills for Hanami, dry-rb, and ROM Ruby development. Covers actions, slices, repositories, relations, changesets, providers, DI, operations, TDD, CLI, views, routing, and validation. Shared Ruby process skills have moved to ruby-core-skills. Uses Markdown + Front-matter architecture.
92
94%
Does it follow best practices?
Impact
92%
1.33xAverage score across 35 eval scenarios
Passed
No known issues
This document details serializer conventions, dedicated serializer class patterns, and testing strategies for Hanami JSON APIs.
For anything beyond extremely simple key-value outputs, extract serialization logic into a dedicated class. This isolates representation concerns from the Action class and keeps code DRY.
# app/serializers/user_serializer.rb
# frozen_string_literal: true
module MyApp
module Serializers
class UserSerializer
def initialize(user)
@user = user
end
# Define a clear representation hash
def to_h
{
id: @user.id,
email: @user.email,
name: "#{@user.first_name} #{@user.last_name}",
role: @user.role,
created_at: @user.created_at.iso8601 # Always format timestamps explicitly
}
end
# Standard interface expected by JSON encoders
def to_json(*args)
to_h.to_json(*args)
end
end
end
endTo guarantee your serializers produce predictable and parseable JSON output, always verify them with a round-trip parse:
# Example inside a unit spec or REPL:
user = user_repo.by_id(1).one
serialized = UserSerializer.new(user).to_json
parsed = JSON.parse(serialized, symbolize_names: true)
# Assertions to ensure parseable equivalence:
assert_equal user.id, parsed[:id]
assert_equal user.email, parsed[:email].to_json on the serializer instance.JSON.parse(serialized, symbolize_names: true).to_h in your serializer:
Time#to_s formatting. Use .iso8601 for standard-compliant timestamps.to_h. Never do generic loops or select all attributes from a repository model, as it risks leaking internal database fields (like password_digest or internal flags).NoMethodError during serialization:
last_login_at: @user.last_login_at&.iso8601docs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
scenario-17
scenario-18
scenario-19
scenario-20
scenario-21
scenario-22
scenario-23
scenario-24
scenario-25
scenario-26
scenario-27
scenario-28
scenario-29
scenario-30
scenario-31
scenario-32
scenario-33
scenario-34
scenario-35
skills
actions
build-json-api
create-action
handle-errors
validate-params
context
load-context
db
create-changeset
create-repository
define-relation
write-migration
dry-monads
handle-result-pattern
dry-rb
create-operation
create-validation-contract
providers
configure-providers
implement-di
review-security
routing
define-routes
slices
configure-slice
create-slice
extract-slice
review-slice-boundaries
test-slice