CtrlK
BlogDocsLog inGet started
Tessl Logo

igmarin/ruby-core-skills

Curated library of 16 public Ruby AI agent skills: 10 atomic skills (YARD docs, service objects, calculator pattern, API clients, DDD, bug triage, code review, skill routing), 5 process-discipline skills (TDD, refactoring, review, security, test planning), and 1 planning skill (TDD task generation). Zero agents — this is a foundational library consumed by framework-specific tiles like rails-agent-skills and hanakai-yaku.

95

1.05x
Quality

96%

Does it follow best practices?

Impact

95%

1.05x

Average score across 16 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

SKILL.mdskills/patterns/create-service-object/

name:
create-service-object
license:
MIT
description:
Use when creating or refactoring Ruby service classes with `def self.call(...)`→`new(...).call` entry point, `{success: true/false, response: {...}}` response contract (error: `{success: false, response: {error: {message: string}}}`), must catch `StandardError` + log with `logger.error` + use `UPPER_SNAKE_CASE` error constants, spec at `spec/services/[module]/[name]_spec.rb`, impl at `services/[module]/[name].rb`, mandatory module README even for single-service modules, tests assert `success:` and `response:` keys, test command+failure output in artifact — and MUST write failing test BEFORE implementation. Covers 9 quick-ref rules, 4 core patterns (Standard, Batch, Static/Class-only, Orchestrator), `.call` ≤20 lines, YARD on self.call and #call. Trigger words: service object, .call pattern, services, service module, response hash, success/response shape, YARD on self.call, service skeleton, module README, orchestrator.
metadata:
{"version":"1.0.0","user-invocable":"true","origin":"Extracted from igmarin/rails-agent-skills v5.1.17"}

Create Service Object

Quick Reference

AspectRule
Entry pointdef self.call(...)new(...).call
ValidationValidate inputs at top of call; return error hash if invalid
Error handlingrescue → log + error hash; never re-raise to caller
TransactionsOnly wrap multi-step database operations that must be atomic
call length≤20 lines; extract sub-services if longer
ScopeReturn data only (no HTTP/UI concerns); single responsibility per service
SQLUse query sanitization for any dynamic queries
Shared logicExtract validators to class-only services (Pattern 3)
Response dataSerialize domain data; do not return raw persistence model objects (e.g. ActiveRecord, ROM) in response
Response shape{ success: true/false, response: { ... } } always

HARD-GATE

TESTS GATE IMPLEMENTATION:
EVERY service object MUST have its test written and validated BEFORE implementation.
  1. Write the spec/test for .call (with contexts for success, error, edge cases)
  2. Run the spec/test — verify it fails because the service does not exist yet
  3. ONLY THEN write the service implementation
The final artifact must include the test command and the failure message
before implementation. Use the observed failure when available; otherwise show
the exact expected failure class/message for the missing service.
See tdd-process for the full gate cycle.

Core Process

  1. Write Spec (Test-First): Create the spec/test file under the testing directory (e.g. spec/services/<module_name>/<service_name>_spec.rb or test/services/). Cover success and error paths for .call. Run it to confirm it fails (see HARD-GATE).
  2. Define Service Skeleton: Create the file under the service directory (e.g., services/<module_name>/<service_name>.rb or lib/services/) with the correct module namespace.
  3. Select Pattern: Choose Standard, Batch, Class-only (Pattern 3), or Orchestrator based on requirements.
  4. Implement Contract: Implement self.call and #call. The response must always be { success: true, response: { ... } } or { success: false, response: { error: { message: '...' } } }.
  5. Handle Errors and Logging: Catch StandardError (and domain exceptions). Log with the application logger (e.g., logger.error). Use UPPER_SNAKE_CASE constants for all user-facing error strings.
  6. Add YARD Documentation: Add @param, @return [Hash], and @raise tags to self.call and every other public method. Document self.call separately from #call.
  7. Write Module README: Generate services/<module_name>/README.md explaining domain context. Required even for single-service modules.

Core Patterns

1. The .call Pattern

def self.call(params)
  new(params).call
end

def call
  # ... processing ...
  { success: true, response: { data: result } }
rescue StandardError => e
  logger.error("Processing Error: #{e.message}")
  logger.error(e.backtrace.join("\n"))
  { success: false, response: { error: { message: ERROR_MESSAGE } } }
end

2. Batch Processing + Per-Item Rescue (Partial Success)

def call
  results = @items.each_with_object({ successful: [], failed: [] }) do |item, acc|
    # process...
  rescue StandardError => e
    logger.error("Unexpected item error: #{e.message}")
    acc[:failed] << { sku: item[:sku], error: e.message }
  end
  { success: true, response: results }
end

3. Class-only Services (Static Methods)

When no instance state is needed, use ONLY class methods — no initialize, no instance variables. Suitable for validators, formatters, and argument-only helpers.

class Orders::QuantityValidator
  def self.call(quantity:)
    return { success: false, response: { error: { message: INVALID_QUANTITY } } } unless quantity.positive?

    { success: true, response: { valid: true } }
  end
end

4. Orchestrator Delegation (≤20-line call)

def call
  user_result = UserCreationService.call(@params)
  return user_result unless user_result[:success]
  # ... continue ...
end

Output Style

Every service-object task produces these artifacts:

  1. Service fileservices/<module_name>/<service_name>.rb (pragma on line 1, class wrapped in a module matching the directory name).
  2. YARD docs@param, @return [Hash], and @raise on self.call and every other public method (self.call documented separately from #call).
  3. Error message constants — user-facing strings in UPPER_SNAKE_CASE at the top of the class, never inline in a rescue.
  4. Module READMEservices/<module_name>/README.md, required even for single-service modules.
  5. Spec filespec/services/<module_name>/<service_name>_spec.rb (or equivalent test runner file), written and failing BEFORE implementation (see HARD-GATE). Tests must assert success: and response: top-level keys and the meaningful payload shape.
  6. Stateless pattern decision — State whether instance state is required. If not, use Pattern 3 (no initialize, no instance variables).
  7. Language — YARD, README, and error messages in English unless the user requests otherwise.

For class-only services (Pattern 3), document public class methods in YARD; if the class returns a non-standard shape (e.g. nil / error string), document that explicitly in YARD and the README.

Extended Resources (Progressive Disclosure)

Load these files only when their specific content is needed:

  • assets/examples.md — Detailed examples of the 4 core patterns (Standard, Batch, Static, Orchestrator).
  • assets/service_skeleton.md — Basic starting skeleton.
  • assets/module_readme_template.md — Template for the mandatory module README.

Integration

SkillWhen to chain
write-yard-docsWriting/reviewing inline docs
integrate-api-clientExternal API integrations
implement-calculator-patternVariant-based calculators
write-testsGeneral testing structure
refactor-processRefactoring service objects

skills

README.md

tile.json