CtrlK
BlogDocsLog inGet started
Tessl Logo

igmarin/hanakai-yaku

Curated library of atomic skills and personas for Hanami, dry-rb, and ROM Ruby development. Covers actions, slices, repositories, relations, changesets, providers, DI, operations, TDD, CLI, views, routing, validation, and 10 orchestration personas. Shared Ruby process skills have moved to ruby-core-skills. Uses Markdown + Front-matter architecture.

95

1.20x
Quality

95%

Does it follow best practices?

Impact

96%

1.20x

Average score across 45 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

SKILL.mdskills/db/define-relation/

name:
define-relation
license:
MIT
type:
atomic
description:
Use when defining ROM Relations that map to database tables in Hanami 2.x — inherit from `Hanami::DB::Relation` with `schema :table_name, infer: true` for automatic schema introspection or explicit `schema :table_name do ... end` with typed attributes, add custom query methods as public relation methods returning filtered/reordered relations, define associations via `many_to_one`/`one_to_many` with `as:` aliases and load strategies using `combine` for eager-loading, and keep relations in sync with migrations by verifying via console. Trigger terms: ROM Relations, schema inference, associations, query methods, combine, eager-loading.
metadata:
{"ecosystem_sources":["rom-rb/rom","rom-rb/rom-sql","hanami/hanami-db"],"tags":["db","rom","relations","queries"],"version":"1.0.0"}

define-relation

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.


Quick Reference

ScenarioApproach
Define a RelationClass inherits from Hanami::DB::Relation with schema :table_name, infer: true
Infer schema from DBschema :table_name, infer: true
Define explicit schemaschema :table_name do { attribute :id, Types::Integer } end
Add a custom query methodDefine a method that returns a restricted/ordered relation
Define an associationmany_to_one :users, as: :user or one_to_many :posts, as: :posts
Access the Relation in an Actioninclude Deps["relations.users"]
Call a query methodrelations.users.active or relations.users.by_email("a@b.com")
Verify inferred schemabundle exec hanami consoleapp['relations.users'].schema

Core Rules

  1. 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
    end
  2. Use infer: true for new tables where the database schema is the source of truth. ROM will introspect the table at boot.

  3. 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
    end
  4. Add query methods for reusable filters. Encapsulate all query filters inside public relation methods — keep business logic, validations, and side effects out of Relations:

    def active
      where(status: "active")
    end
    
    def by_email(email)
      where(email: email)
    end
  5. Define associations: Use the association DSL macros for basic and advanced linkage between tables:

    associations do
      # Basic cases
      many_to_one :users, as: :author
      one_to_many :posts, as: :posts
    
      # Aliased foreign key
      many_to_one :users, foreign_key: :author_id, as: :author
    
      # Nested / through association
      one_to_many :comments, through: :posts
    end

    Loading strategies: use combine to eagerly load associations in a single composed query, or load to issue a separate query:

    # In a repository or relation method:
    users.combine(:posts)           # eager-load posts into each user struct
    users.combine(posts: :comments) # nested eager-load
  6. Keep 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"].schema

    If schema mismatch or boot failure: check migration status → run pending migrations (bundle exec hanami db migrate) → restart the console → re-verify the schema. If infer: true fails at boot, confirm the table exists in the database and that the connection configuration is correct.


Common Mistakes

MistakeResolution
Redundant declarationsDo not declare explicit attributes for columns that are already auto-inferred (causes boot errors).
Direct View accessBypassing the Repository layer to query relations directly in views is an anti-pattern.
Singular class namesRelations map to plural database tables and must be plural: Users, not User.

For detailed relation pattern examples, see RELATIONS.md.

Integration

Related SkillWhen to chain
write-migrationAfter any migration that changes the schema — verify Relation still matches
create-repositoryWhen you need domain-level read/write operations that wrap Relations
define-entityWhen defining the data structures returned by Relations
write-rom-spec (testing)When writing tests for Relation query methods
build-crud-resourceFull end-to-end: Relation → Repository → Action → View → Test

skills

README.md

tile.json