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

SKILL.mdskills/views/decorate-with-parts/

name:
decorate-with-parts
license:
MIT
description:
Use when creating View Parts in Hanami 2.x, adding a part class, wrapping exposures in Hanami::View::Part, formatting attributes for display, or adding custom helper methods to view objects. Defines Part classes that encapsulate presentation logic (formatted strings, predicates, delegated attributes), exposes them via the `expose` macro, and keeps templates and Views free of complex formatting. Use when working with view decoration, view objects, template helpers, or the Ruby view layer in a Hanami application.
metadata:
{"ecosystem_sources":["hanami/hanami-view"],"tags":["views","parts","decorators","presentation"],"version":"1.0.0"}

decorate-with-parts

Use this skill when creating View Parts for decorator-style logic in Hanami 2.x.

Core principle: Parts wrap data with presentation methods. They keep Views and templates free of complex formatting logic.


Quick Reference

ScenarioApproach
Create a PartClass inherits from Hanami::View::Part
Expose as a Partexpose :user, as: :user_part
Define Part methodsAdd methods to the Part class for presentation logic
Access wrapped datavalue method returns the raw underlying object
Delegate to wrapped datadelegate :name, :email, to: :value
Use in template<%= user_part.display_name %>
Format datadef formatted_date; value.created_at.strftime("%B %d, %Y"); end
Generate HTMLKeep HTML generation out of Parts. Use helpers or template logic.

Core Rules

  1. Create the Part class:

    # app/views/parts/user.rb
    # frozen_string_literal: true
    
    module MyApp
      module Views
        module Parts
          class User < Hanami::View::Part
            delegate :name, :email, to: :value
    
            def display_name
              "#{value.first_name} #{value.last_name}"
            end
    
            def member_since
              value.created_at.strftime("%B %Y")
            end
    
            def admin?
              value.role == "admin"
            end
          end
        end
      end
    end
  2. Expose data as a Part in the View:

    class Show < MyApp::View
      expose :user, as: :user_part
    end
  3. Use Part methods in templates:

    <h1><%= user_part.display_name %></h1>
    <p>Member since <%= user_part.member_since %></p>
    
    <% if user_part.admin? %>
      <span class="badge">Admin</span>
    <% end %>
  4. Keep Parts focused on presentation. No database queries, no business rules:

    # GOOD: formatting and simple predicates
    def display_name
      "#{value.first_name} #{value.last_name}"
    end
    
    # BAD: business logic
    def can_delete?(resource)
      value.role == "admin" && resource.owner_id == value.id
    end
  5. Delegate common methods to the wrapped value:

    delegate :id, :name, :email, :created_at, to: :value
  6. Access the raw value with the value method when needed:

    def raw_attributes
      value.to_h
    end
  7. Do not generate HTML in Parts. Parts return strings or booleans. Templates handle HTML:

    # GOOD
    def status_label
      value.active? ? "Active" : "Inactive"
    end
    
    # BAD
    def status_badge
      "<span class='badge'>#{status_label}</span>"
    end

Common Mistakes

  • No database queries in Parts. Parts wrap already-fetched data; queries belong in repositories or actions.
  • No HTML generation in Parts. Parts return plain strings or booleans; templates produce HTML markup.
  • No business logic in Parts. Predicates based on simple attribute values are fine; authorization rules and domain decisions belong in interactors or service objects.

Integration

Related SkillWhen to chain
create-viewParts are used within Views. Master View structure first.
create-actionActions pass data to Views, which wrap them in Parts.
define-entityParts often wrap Entity objects returned by Repositories.

skills

views

decorate-with-parts

README.md

tile.json