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
Use this skill when defining ROM Relations that map to database tables in Hanami 2.x.
Core principle: The Relation is the query layer. It defines how to read and filter data, not business logic.
| Scenario | Approach |
|---|---|
| Define a Relation | Class inherits from Hanami::DB::Relation with schema :table_name, infer: true |
| Infer schema from DB | schema :table_name, infer: true |
| Define explicit schema | schema :table_name do { attribute :id, Types::Integer } end |
| Add a custom query method | Define a method that returns a restricted/ordered relation |
| Define an association | many_to_one :users, as: :user or one_to_many :posts, as: :posts |
| Access the Relation in an Action | include Deps["relations.users"] |
| Call a query method | relations.users.active or relations.users.by_email("a@b.com") |
| Verify inferred schema | bundle exec hanami console → app['relations.users'].schema |
Create the Relation file in the app or slice:
# app/relations/users.rb
# frozen_string_literal: true
module MyApp
module Relations
class Users < Hanami::DB::Relation
schema :users, infer: true
end
end
endUse infer: true for new tables where the database schema is the source of truth. ROM will introspect the table at boot.
Define explicit schema when you need custom type coercion or virtual attributes:
schema :users do
attribute :id, Types::Integer
attribute :email, Types::String
attribute :created_at, Types::Time
endAdd query methods for reusable filters:
def active
where(status: "active")
end
def by_email(email)
where(email: email)
endDefine associations: Link related tables using association DSL macros. For complete association setup and advanced configurations, see RELATIONS.md.
associations do
many_to_one :users, as: :author
one_to_many :posts, as: :posts
endFilter queries via custom methods: Encapsulate query filters inside public relation methods:
def active
where(status: "active")
endKeep Relations in sync with migrations:
If not using infer: true, manually sync explicit schema declarations when migrations alter the database. Verify using the console:
bundle exec hanami console
# check app["relations.users"].schemaNever put business logic in Relations: Relations are the query construction layer. Do not place validations or side effects here; those belong in Operations, Repositories, or actions.
| Mistake | Resolution |
|---|---|
| Redundant declarations | Do not declare explicit attributes for columns that are already auto-inferred (causes boot errors). |
| Direct View access | Bypassing the Repository layer to query relations directly in views is an anti-pattern. |
| Singular class names | Relations map to plural database tables and must be plural: Users, not User. |
| Related Skill | When to chain |
|---|---|
| write-migration | After any migration that changes the schema — verify Relation still matches |
| create-repository | When you need domain-level read/write operations that wrap Relations |
| define-entity | When defining the data structures returned by Relations |
| write-rom-spec (testing) | When writing tests for Relation query methods |
| build-crud-resource | Full end-to-end: Relation → Repository → Action → View → Test |
docs
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