{"id":13878249,"url":"https://github.com/benpickles/operatic","last_synced_at":"2026-03-05T10:32:21.637Z","repository":{"id":36267426,"uuid":"206566569","full_name":"benpickles/operatic","owner":"benpickles","description":"🗣️ A minimal standard interface for your Ruby operations","archived":false,"fork":false,"pushed_at":"2025-08-12T15:18:17.000Z","size":57,"stargazers_count":23,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-08T01:29:07.815Z","etag":null,"topics":["ruby"],"latest_commit_sha":null,"homepage":"https://www.benpickles.com/articles/87-announcing-operatic","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benpickles.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-09-05T13:08:58.000Z","updated_at":"2025-09-09T20:35:57.000Z","dependencies_parsed_at":"2024-05-15T23:14:53.899Z","dependency_job_id":"2a980793-fd89-4a2f-9e76-cf457b4b852f","html_url":"https://github.com/benpickles/operatic","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/benpickles/operatic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benpickles%2Foperatic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benpickles%2Foperatic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benpickles%2Foperatic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benpickles%2Foperatic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benpickles","download_url":"https://codeload.github.com/benpickles/operatic/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benpickles%2Foperatic/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30119430,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T09:35:22.236Z","status":"ssl_error","status_checked_at":"2026-03-05T09:35:20.028Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ruby"],"created_at":"2024-08-06T08:01:43.928Z","updated_at":"2026-03-05T10:32:21.601Z","avatar_url":"https://github.com/benpickles.png","language":"Ruby","readme":"# Operatic\n\n[![GitHub Actions status](https://github.com/benpickles/operatic/workflows/Ruby/badge.svg)](https://github.com/benpickles/operatic)\n\nA minimal standard interface for your operations.\n\n## Installation\n\nAdd Operatic to your application's Gemfile and run `bundle install`.\n\n```ruby\ngem 'operatic'\n```\n\n## Usage\n\nAn Operatic class encapsulates an operation and communicates its status via a result object. As well as being a `#success?` or `#failure?` data can also be attached to the result via `#success!`, `#failure!`, or during the operation's execution.\n\n```ruby\nclass SayHello\n  include Operatic\n\n  # Readers for instance variables defined in `.call`.\n  attr_reader :name\n\n  # Declare convenience data accessors.\n  data_attr :message\n\n  def call\n    # Exit the method and mark the operation as a failure.\n    return failure! unless name\n\n    # Mark the operation as a success and attach further data.\n    success!(message: \"Hello #{name}\")\n  end\nend\n\nresult = SayHello.call(name: 'Dave')\nresult.class     # =\u003e Operatic::Success\nresult.failure?  # =\u003e false\nresult.success?  # =\u003e true\nresult.message   # =\u003e \"Hello Dave\"\nresult[:message] # =\u003e \"Hello Dave\"\nresult.to_h      # =\u003e {:message=\u003e\"Hello Dave\"}\n\nresult = SayHello.call\nresult.class     # =\u003e Operatic::Failure\nresult.failure?  # =\u003e true\nresult.success?  # =\u003e false\nresult.message   # =\u003e nil\nresult[:message] # =\u003e nil\nresult.to_h      # =\u003e {}\n```\n\nA Rails controller might use Operatic like this:\n\n```ruby\nclass HellosController \u003c ApplicationController\n  def create\n    result = SayHello.call(name: params[:name])\n\n    if result.success?\n      render plain: result.message\n    else\n      render :new\n    end\n  end\nend\n```\n\n## Pattern matching\n\nAn Operatic result also supports pattern matching allowing you to match over a tuple of the result class and its data:\n\n```ruby\ncase SayHello.call(name: 'Dave')\nin [Operatic::Success, { message: }]\n  # Result is a success, do something with the `message` variable.\nin [Operatic::Failure, _]\n  # Result is a failure, do something else.\nend\n```\n\nOr match solely against its data:\n\n```ruby\ncase SayHello.call(name: 'Dave')\nin message:\n  # Result has the `message` key, do something with the variable.\nelse\n  # Do something else.\nend\n```\n\nWhich might be consumed in Rails like this:\n\n```ruby\nclass HellosController \u003c ApplicationController\n  def create\n    case SayHello.call(name: params[:name])\n    in [Operatic::Success, { message: }]\n      render plain: message\n    in [Operatic::Failure, _]\n      render :new\n    end\n  end\nend\n```\n\n## Development\n\nRun the tests with:\n\n```\nbundle exec rspec\n```\n\nGenerate Yard documentation with:\n\n```\nbundle exec yardoc\n```\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Operatic project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/benpickles/operatic/blob/main/CODE_OF_CONDUCT.md).\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenpickles%2Foperatic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenpickles%2Foperatic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenpickles%2Foperatic/lists"}