igmarin/ruby-core-skills

create-service-object

Use when creating or refactoring Ruby service classes following the `def self.call(...)` → `new(...).call` entry point pattern with a strict `{ success: true/false, response: { ... } }` response contract. Handles error shape (`{ success: false, response: { error: { message: string } } }`), `StandardError` rescue with `logger.error` logging, `UPPER_SNAKE_CASE` error constants, and mandatory module READMEs. Enforces test-first workflow: spec written and confirmed failing before implementation. Co…

First seen Jul 28, 2026

Installation

$ npx skills add igmarin/ruby-core-skills --skill create-service-object

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from igmarin/ruby-core-skills · top by installs.

npx skills add igmarin/ruby-core-skills

Browse all from igmarin/ruby-core-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 2
License LICENSE
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
LicenseMIT
More metadata
version
1.0.0
user-invocable
true
origin
Extracted from igmarin/rails-agent-skills v5.1.17

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,143 B
  • docs SUMMARY.md 953 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 19 installs

SKILL.md

Create Service Object

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 at spec/services/<modulename>/<servicename>_spec.rb (or test/services/). Cover success and error paths for .call. Run it to confirm it fails (see HARD-GATE). Tests must assert success: and response: top-level keys and the meaningful payload shape.
  2. Define Service Skeleton: Create services/<modulename>/<servicename>.rb with the correct module namespace.
  3. Select Pattern: Choose Standard, Batch, Class-only (Pattern 3), or Orchestrator based on requirements. State whether instance state is required — if not, use Pattern 3 (no initialize, no instance variables).
  4. Implement Contract: Implement self.call and #call. Response must always be { success: true, response: { ... } } or { success: false, response: { error: { message: '...' } } }. Keep call ≤ 20 lines; extract sub-services if longer. Validate inputs at top of call; return error hash if invalid. Return serialized data only — no raw persistence model objects (e.g. ActiveRecord, ROM) in response.
  5. Handle Errors and Logging: Catch StandardError (and domain exceptions). Log with the application logger (e.g., logger.error). Use UPPERSNAKECASE constants for all user-facing error strings — never inline in a rescue. Never re-raise to caller.
  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. For class-only services (Pattern 3), if the class returns a non-standard shape (e.g. nil / error string), document that explicitly in YARD and the README.
  7. Write Module README: Generate services/<module_name>/README.md explaining domain context. Required even for single-service modules.

Additional Constraints

Aspect Rule
Transactions Only wrap multi-step database operations that must be atomic
Scope Return data only (no HTTP/UI concerns); single responsibility per service
SQL Use query sanitization for any dynamic queries
Shared logic Extract validators to class-only services (Pattern 3)

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

Extended Resources (Progressive Disclosure)

Load these files only when their specific content is needed:

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

Integration

Skill When to chain
write-yard-docs Writing/reviewing inline docs
integrate-api-client External API integrations
implement-calculator-pattern Variant-based calculators
write-tests General testing structure
refactor-process Refactoring service objects