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
95%
Does it follow best practices?
Impact
96%
1.20xAverage score across 45 eval scenarios
Passed
No known issues
Use this skill when writing specs for ROM Relations and Repositories in Hanami 2.x.
Follow these steps in order, treating each as a checkpoint:
Before writing any spec, ensure every test is wrapped in a transaction that rolls back. Place this in a shared context (e.g., spec/support/db_rollback.rb) and include it in your repo/relation specs:
# spec/support/db_rollback.rb
RSpec.shared_context "db rollback" do
around do |example|
rom = Hanami.app["persistence.rom"]
rom.gateways[:default].connection.transaction(rollback: :always, auto_savepoint: true) do
example.run
end
end
endThen include it via metadata in spec/spec_helper.rb:
RSpec.configure do |config|
config.include_context "db rollback", type: :repo
config.include_context "db rollback", type: :relation
endPlace it under spec/relations/ or spec/repos/. Initialize relation or repo in a let block and define all test data inline:
# spec/repos/users_spec.rb
RSpec.describe MyApp::Repos::UserRepo, type: :repo do
let(:repo) { described_class.new }
it "creates and finds a user by email" do
user = repo.create(email: "alice@example.com", name: "Alice")
expect(user.id).not_to be_nil
found = repo.find_by_email("alice@example.com")
expect(found.name).to eq("Alice")
end
it "updates a user" do
user = repo.create(email: "alice@example.com", first_name: "Alice")
repo.update(user.id, first_name: "Alicia")
expect(repo.by_id(user.id).one.first_name).to eq("Alicia")
end
it "raises when user is not found" do
expect { repo.by_id(99999).one! }.to raise_error(ROM::TupleCountMismatchError)
end
end# spec/relations/users_spec.rb
RSpec.describe MyApp::Relations::Users, type: :relation do
let(:relation) { Hanami.app["persistence.rom"].relations[:users] }
let!(:alice) { relation.insert(email: "alice@example.com", active: true) }
let!(:bob) { relation.insert(email: "bob@example.com", active: false) }
it "returns active users" do
active_users = relation.active.to_a
expect(active_users.length).to eq(1)
expect(active_users.first[:email]).to eq("alice@example.com")
end
endConfirm the spec fails, then write only the minimal ROM query or persistence logic to make it pass:
bundle exec rspec spec/repos/users_spec.rb # expect failure
# implement the relation/repo method …
bundle exec rspec spec/repos/users_spec.rb # expect greenbefore(:all) for database data setup, which operates outside individual test transaction boundaries.| Related Skill | When to chain |
|---|---|
| create-repository | Repository creation precedes spec implementation. |
| define-relation | Relation definitions are verified via custom specs. |
.tessl-plugin
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
scenario-36
scenario-37
scenario-38
scenario-39
scenario-40
scenario-41
scenario-42
scenario-43
scenario-44
scenario-45
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
personas
providers
configure-providers
implement-di
review-security
routing
define-routes
slices
configure-slice
create-slice
extract-slice
review-slice-boundaries
test-slice