CtrlK
BlogDocsLog inGet started
Tessl Logo

igmarin/hanakai-yaku

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

1.33x
Quality

94%

Does it follow best practices?

Impact

92%

1.33x

Average score across 35 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

CHANGESET_PATTERNS.mdskills/db/create-changeset/

Changeset Patterns

Create Changeset with Timestamps

module Api
  module Changesets
    class CreateUser < ROM::Changeset::Create
      map do |attrs|
        now = Time.now
        attrs.merge(created_at: now, updated_at: now)
      end
    end
  end
end

Update Changeset with Allowed Keys

class UpdateUser < ROM::Changeset::Update
  map do |attrs|
    attrs.merge(updated_at: Time.now)
  end

  def allowed_keys
    [:name, :email, :role]
  end

  # Never allow these fields to be mass-updated
  def disallowed_keys
    [:encrypted_password, :admin, :id]
  end
end

Changeset with Contract Validation

class CreateUser < ROM::Changeset::Create
  map do |attrs|
    attrs.merge(created_at: Time.now)
  end

  def default_contract
    Users::CreateContract.new
  end
end

The changeset calls the contract before persisting. If validation fails, the changeset raises a ROM::CommandError.

Composing Changesets

# Chain: validate → set defaults → persist
users.changeset(CreateUser, attrs)
     .map { |attrs| attrs.merge(created_by: current_user.id) }
     .commit

Testing Changesets

RSpec.describe Api::Changesets::CreateUser do
  let(:changeset) { user_repo.users.changeset(described_class, attrs) }

  context "with valid attrs" do
    let(:attrs) { { email: "test@example.com", name: "Test" } }

    it "creates a user with timestamps" do
      result = changeset.commit
      expect(result.email).to eq("test@example.com")
      expect(result.created_at).to be_a(Time)
    end
  end
end

skills

README.md

tile.json