{"id":18319774,"url":"https://github.com/redding/much-result","last_synced_at":"2025-04-05T22:31:37.341Z","repository":{"id":55102489,"uuid":"289713047","full_name":"redding/much-result","owner":"redding","description":"API for managing the results of operations.","archived":false,"fork":false,"pushed_at":"2022-04-02T20:20:44.000Z","size":77,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-25T20:00:39.084Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/redding.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-23T15:24:54.000Z","updated_at":"2021-01-10T14:27:21.000Z","dependencies_parsed_at":"2022-08-14T12:00:59.798Z","dependency_job_id":null,"html_url":"https://github.com/redding/much-result","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fmuch-result","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fmuch-result/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fmuch-result/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fmuch-result/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redding","download_url":"https://codeload.github.com/redding/much-result/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247411236,"owners_count":20934650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-11-05T18:14:13.084Z","updated_at":"2025-04-05T22:31:36.967Z","avatar_url":"https://github.com/redding.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MuchResult\n\nAPI for managing the results of operations.\n\n## Usage\n\nHave services/methods return a MuchResult based on the whether an exception was raised or not:\n\n```ruby\nclass PerformSomeOperation\n  def self.call\n    # Do something that could fail by raising an exception.\n    MuchResult.success(message: \"it worked!\")\n  rescue =\u003e exception\n    MuchResult.failure(exception: exception)\n  end\nend\n\nresult = PerformSomeOperation.call\n\nresult.success?    # =\u003e true\nresult.failure?    # =\u003e false\nresult.message     # =\u003e \"it worked!\"\nresult.sub_results # =\u003e []\n```\n\nHave services/methods return a MuchResult based on a result value (i.e. \"truthy\" = success; \"false-y\" = failure):\n\n```ruby\ndef perform_some_operation(success:)\n  # Do something that could fail.\n  MuchResult.for(success, message: \"it ran :shrug:\")\nend\n\nresult = perform_some_operation(success: true)\nresult.success? # =\u003e true\nresult.failure? # =\u003e false\nresult.message  # =\u003e \"it ran :shrug:\"\n\nresult = perform_some_operation(success: false)\nresult.success? # =\u003e false\nresult.failure? # =\u003e true\nresult.message  # =\u003e \"it ran :shrug:\"\n\nresult = perform_some_operation(success: nil)\nresult.success? # =\u003e false\nresult.failure? # =\u003e true\nresult.message  # =\u003e \"it ran :shrug:\"\n```\n\nSet arbitrary values on MuchResults before or after they are created:\n\n```ruby\nresult = MuchResult.success(message: \"it worked!\")\nresult.set(\n  other_value1: \"something else 1\",\n  other_value2: \"something else 2\"\n)\nresult.message      # =\u003e \"it worked!\"\nresult.other_value1 # =\u003e \"something else 1\"\nresult.other_value2 # =\u003e \"something else 2\"\n\nresult.attribute_names # =\u003e [:message, :other_value1, :other_value2]\n\nresult.attributes\n# =\u003e {\n#  message: \"it worked!\",\n#  other_value1: \"something else 1\",\n#  other_value2: \"something else 2\"\n# }\n```\n\n### Capture sub-Results\n\nCapture MuchResults for sub-operations into a parent MuchResult:\n\n```ruby\nclass PerformSomeOperation\n  def self.call\n    MuchResult.tap(description: \"Do both parts\") { |result|\n      result          # =\u003e \u003cMuchResult ...\u003e\n      result.success? # =\u003e true\n\n      result.capture { do_part_1 }\n      # OR you can use `capture_all` to capture from an Array of MuchResults\n\n      # raise an Exception if failure\n      result.capture! { do_part_2 }\n      # OR you can use `capture_all!` to capture from an Array of MuchResults\n\n      # set some arbitrary values b/c it worked.\n      result.set(message: \"it worked!\")\n    } # =\u003e result\n  end\n\n  def self.do_part_1\n    MuchResult.failure(description: \"Part 1\")\n  end\n\n  def self.do_part_2\n    MuchResult.success(description: \"Part 2\")\n  end\nend\n\nresult = PerformSomeOperation.call\n\nresult.success? # =\u003e true\nresult.message  # =\u003e \"it worked!\"\n\n# Get just the immediate sub-results that were captured for the MuchResult.\nresult.sub_results # =\u003e [\u003cMuchResult Part 1\u003e, \u003cMuchResult Part 2\u003e]\n\n# Get all MuchResults that make up this MuchResult (including those captured\n# on all recursive sub-results).\nresult.all_results # =\u003e [result, \u003cMuchResult Part 1\u003e, \u003cMuchResult Part 2\u003e]\n\n# Get aggregated values for each MuchResult that makes up this MuchResult.\nresult.get_for_sub_results(:description)\n# =\u003e [\"Part 1\", \"Part 2\"]\nresult.get_for_success_sub_results(:description)\n# =\u003e [\"Part 2\"]\nresult.get_for_failure_sub_results(:description)\n# =\u003e [\"Part 1\"]\n\nresult.get_for_all_results(:description)\n# =\u003e [\"Do both parts\", \"Part 1\", \"Part 2\"]\nresult.get_for_all_success_results(:description)\n# =\u003e [\"Part 2\"]\nresult.get_for_all_failure_results(:description)\n# =\u003e [\"Do both parts\", \"Part 1\"]\n```\n\n### Transactions\n\nRun transactions capturing sub-Results:\n\n```ruby\nclass PerformSomeOperation\n  def self.call\n    MuchResult.transaction(\n      ActiveRecord::Base,\n      value: \"something\",\n      description: \"Do both parts\"\n    ) { |transaction|\n      transaction        # =\u003e \u003cMuchResult::Transaction ...\u003e\n      transaction.result # =\u003e \u003cMuchResult ...\u003e\n\n      # You can interact with a transaction as if it were a MuchResult.\n      transaction.value    # =\u003e \"something\"\n      transaction.success? # =\u003e true\n\n      transaction.capture { do_part_1 }\n      # OR you can use `capture_all` to capture from an Array of MuchResults\n\n      # raise an Exception if failure (which will rollback the transaction)\n      transaction.capture! { do_part_2 }\n      # OR you can use `capture_all!` to capture from an Array of MuchResults\n\n      # manually rollback the transaction if needed\n      # (stops processing and doesn't commit the transaction)\n      transaction.rollback if rollback_needed?\n\n      # manually halt the transaction if needed\n      # (stops processing and commits the transaction)\n      transaction.halt if halt_needed?\n\n      # set some arbitrary values b/c it worked.\n      transaction.set(message: \"it worked!\")\n    } # =\u003e transaction.result\n  end\n\n  def self.do_part_1\n    MuchResult.failure(description: \"Part 1\")\n  end\n\n  def self.do_part_2\n    MuchResult.success(description: \"Part 2\")\n  end\n\n  def rollback_needed?\n    false\n  end\n\n  def halt_needed?\n    false\n  end\nend\n\nresult = PerformSomeOperation.call\n\nresult.success? # =\u003e true\nresult.message  # =\u003e \"it worked!\"\n\nresult.much_result_transaction_rolled_back # =\u003e false\nresult.much_result_transaction_halted      # =\u003e false\n\n# Get just the immediate sub-results that were captured for the MuchResult.\nresult.sub_results # =\u003e [\u003cMuchResult Part 1\u003e, \u003cMuchResult Part 2\u003e]\n\n# Get all MuchResults that make up this MuchResult (including those captured\n# on all recursive sub-results).\nresult.all_results # =\u003e [result, \u003cMuchResult Part 1\u003e, \u003cMuchResult Part 2\u003e]\n\n# Get aggregated values for each MuchResult that makes up this MuchResult.\nresult.get_for_sub_results(:description)\n# =\u003e [\"Part 1\", \"Part 2\"]\nresult.get_for_success_sub_results(:description)\n# =\u003e [\"Part 2\"]\nresult.get_for_failure_sub_results(:description)\n# =\u003e [\"Part 1\"]\n\nresult.get_for_all_results(:description)\n# =\u003e [\"Do both parts\", \"Part 1\", \"Part 2\"]\nresult.get_for_all_success_results(:description)\n# =\u003e [\"Part 2\"]\nresult.get_for_all_failure_results(:description)\n# =\u003e [\"Do both parts\", \"Part 1\"]\n```\n\nNote: MuchResult::Transactions are designed to delegate to their MuchResult. You can interact with a MuchResult::Transaction as if it were a MuchResult.\n\nYou can configure a default transaction receiver (e.g. `ActiveRecord::Base`) in an initializer. Doing so means if no receiver is passed to `MuchResult.transaction`, the default receiver will be used:\n\n```ruby\n# In an initializer or configuration script:\nMuchResult.default_transaction_receiver = ActiveRecord::Base\n\n# Since no receiver is passed, ActiveRecord::Base will be used:\nMuchResult.transaction do |transaction|\n  # ...\nend\n```\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem \"much-result\"\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install much-result\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am \"Added some feature\"`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredding%2Fmuch-result","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredding%2Fmuch-result","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredding%2Fmuch-result/lists"}