{"id":18728763,"url":"https://github.com/rubyonworld/flows","last_synced_at":"2025-10-27T03:13:53.360Z","repository":{"id":174007922,"uuid":"540252337","full_name":"RubyOnWorld/flows","owner":"RubyOnWorld","description":"MRI 2.7.x will be added later, right now (2.7.1) this version of MRI Ruby is too unstable and produce segmentation faults inside RSpec internals.","archived":false,"fork":false,"pushed_at":"2022-09-23T02:41:23.000Z","size":364,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-28T14:26:20.884Z","etag":null,"topics":["mri","ruby","version"],"latest_commit_sha":null,"homepage":"","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/RubyOnWorld.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}},"created_at":"2022-09-23T02:41:05.000Z","updated_at":"2022-09-27T21:09:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"7859f3ec-6d68-4cc2-9f82-ba52d367a482","html_url":"https://github.com/RubyOnWorld/flows","commit_stats":null,"previous_names":["rubyonworld/flows"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RubyOnWorld%2Fflows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RubyOnWorld%2Fflows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RubyOnWorld%2Fflows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RubyOnWorld%2Fflows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RubyOnWorld","download_url":"https://codeload.github.com/RubyOnWorld/flows/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239599039,"owners_count":19665911,"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":["mri","ruby","version"],"created_at":"2024-11-07T14:24:16.716Z","updated_at":"2025-10-27T03:13:53.280Z","avatar_url":"https://github.com/RubyOnWorld.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flows\n\n[![Build Status](https://github.com/ffloyd/flows/workflows/Test/badge.svg)](https://github.com/ffloyd/flows/actions)\n[![codecov](https://codecov.io/gh/ffloyd/flows/branch/master/graph/badge.svg)](https://codecov.io/gh/ffloyd/flows)\n[![Gem Version](https://badge.fury.io/rb/flows.svg)](https://badge.fury.io/rb/flows)\n\nSmall and fast ruby framework for implementing railway-like operations.\nBy design it is close to\n[Trailblazer::Operation](http://trailblazer.to/gems/operation/2.0/),\n[Dry::Transaction](https://dry-rb.org/gems/dry-transaction/) and Rust control\nflow style.\nFlows has simple and flexible DSL for defining operations and matching results.\nAlso `flows` is faster than Ruby's alternatives.\n\n`flows` has no production dependencies so it can be used with any framework.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'flows', '~\u003e 0.5'\n```\n\nAnd then execute:\n\n```sh\nbundle\n```\n\nOr install it yourself as:\n\n```sh\ngem install flows\n```\n\n## Supported Ruby versions\n\nCI tests against last patch versions every day:\n\n* `MRI 2.5.x`\n* `MRI 2.6.x`\n\n`MRI 2.7.x` will be added later, right now (`2.7.1`) this version of MRI Ruby is too\nunstable and produce segmentation faults inside RSpec internals.\n\n## Usage \u0026 Documentation\n\n* [YARD documentation](https://rubydoc.info/github/ffloyd/flows/master) - this\n  link is for master branch. You can also find YARD documentation for any released\n  version after `v0.4.0`. This documentation has a lot of examples, describes\n  motivation behind each abstraction, but lacks some guides and defined conventions.\n* [Guides](https://ffloyd.github.io/flows/#/) - guides, conventions, integration\n  and migration notes. Will be done before `v1.0.0` release. Right now is under development.\n\n## Development\n\n`Flows` is designed to be framework for your business logic. It is a big\nresponsibility. That's why `flows` has near to be sadistic development\nconventions and linter setup.\n\n### Anyone can make Flows even better\n\nIf you see some typos or unclear things in documentation or code - feel free to open\nan issue. Even if you don't have plans to implement a solution - a problem reporting\nwill help development much. We cannot fix what we don't know.\n\n### [Lefthook](https://github.com/Arkweid/lefthook) as a git hook manager\n\nInstallation on MacOS via Homebrew:\n\n```sh\nbrew install Arkweid/lefthook/lefthook\n```\n\nActivation (in the root of the repo):\n\n```sh\nlefthook install\n```\n\nRun hooks manually:\n\n```sh\nlefthook run pre-commit\nlefthook run pre-push\n```\n\nPlease, never turn off the pre-commit and pre-push hooks.\n\n### Rubocop linter\n\n[Rubocop](https://docs.rubocop.org/en/stable/) in this setup is responsible for:\n\n* defining code style (indentation, etc.)\n* suggest performance improvements ([rubocop-performance](https://docs.rubocop.org/projects/performance/en/stable/))\n* forces all that stuff (with some exceptions) to snippets in Markdown files ([rubocop-md](https://github.com/rubocop-hq/rubocop-md))\n* forces unit-testing best practices ([rubocop-rspec](https://docs.rubocop.org/projects/rspec/en/latest/))\n\nRubocop config for library and RSpec files should be close to standard one only\nwith minor amount of exceptions.\n\nCode in Markdown snippets and `/bin` folder can ignore more rules. `/bin` folder\ncontains only development-related scripts and tools so it's ok to ease linter requirements.\n\nRubocop Metrics (ABC-size, method/class length, etc) must not be eased\nglobally. Never.\n\n### Reek linter\n\n[Ruby Reek](https://github.com/troessner/reek) is a very aggressive linter that\nforces you to do a clean OOP design.\n\nYou will be tempted to just shut up this linter many times. But believe me, in 9\nof 10 cases it worth to refactor. And after each such refactoring you will\nunderstand OOP design better and better.\n\n### Rest of the linters\n\n* [MDL](https://github.com/markdownlint/markdownlint) - for consistent format of Markdown files\n* [forspell](https://github.com/kkuprikov/forspell) - for spellchecking in comments and markdown files\n* [inch](http://rrrene.org/inch/) - for documentation coverage suggestions (the\n  only optional linter)\n\n### Default Rake task and CI\n\nDefault rake task (`bundle exec rake`) executes the following checks:\n\n* Rubocop\n* Ruby Reek\n* RSpec\n* Spellcheck (forspell)\n* MarkdownLint (mdl)\n\nCI is also performing default Rake task. So, if you want to reproduce CI error\nlocally - just run `bundle exec rake`.\n\nDefault Rake task is also executed as a pre-push git hook.\n\n### Error reporting\n\nI hope no one will argue that clear errors makes development noticeably faster.\nThat's why _each_ exception in `flows` should be clear and easy to read.\n\nThis cannot be tested automatically: you only can test correctness\nautomatically, convenience can only be tested manually. That's why when you\nintroduce any new `raise` you have to:\n\n* make an error message clear and descriptive\n* add this error to _errors demo CLI_ (`bin/errors`)\n* add this errors to _all the errors demo_ (`bin/all_the_errors`)\n* make sure that error is displayed correctly and follows a style of the rest\n  of implemented errors\n\n`bin/errors` is done using [GLI](https://davetron5000.github.io/gli/) library,\nrun `bin/errors -h` to explore possibilities.\n\n### Performance\n\nRuby is slow. Moreover, Ruby is very slow. Yes, again. In the past time we had\nto compare Ruby with Python. Python was faster and that's why people started to\ncomplain about Ruby performance. That was fixed. But is Ruby fast nowadays? No.\nBecause languages like Clojure, Go, Rust, Elixir appeared and in comparison\nwith any of these languages Ruby is very very slow.\n\nThat's why you **must** be extra careful with performance. Some business\noperations can be executed hundreds or even thousands times per request. Each\nline of code in your abstraction will slow down such request a bit. That's why\nyou should think about each line performance.\n\nAlso, it's nearly impossible to make zero-cost abstractions in Ruby. The best\nthing you can do - to offload calculations to a class loading or initialization\nstep. Sacrifice some warm-up time to make runtime performance better.\n\nAnd to compare performance overhead between different `flows` abstractions\nand another alternatives a benchmarking CLI was done: `bin/benchmark`.\n\nThis CLI is done using GLI, run `bin/benchmark -h` to explore possibilities.\n\nSo far, `flows` offers the best performance among alternatives. And this CLI\nis made to simplify comparison with alternatives and keep `flows` the fastest solution.\n\n### Documentation\n\nEach public API method or module **must** be properly documented with examples\nand motivation behind.\n\nTo run documentation server locally run `bin/docserver`.\n\nRespect `@since` YARD documentation tag. When some module, class or method has any\nAPI change - you have to provide correct `@since` tag value to the documentation.\n\n### Documentation Driven Development\n\nWhen you about to do some work, the following guideline can lead to the best\nresults:\n\n* first, write needed class and method structure without implementation\n* write YARD documentation with motivation and usage examples for each public\n  class, method, module.\n* write unit tests, check that tests are failing\n* write implementation until tests are green\n\nYes, it's TDD approach with documentation step prepended.\n\n### Unit test\n\nEach public API method or module **must** be properly tested. Internal modules\ncan be tested indirectly through public API.\n\nTest coverage **must** be higher than 95%.\n\n### Commit naming\n\nYou **must** follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).\n\nAllowed prefixes since `v0.4.0`:\n\n* `feat:` - for new features\n* `fix:` - for bugfixes\n* `perf:` - for performance improvements\n* `refactor:` - for refactoring work\n* `ci:` - updates for CI configuration\n* `docs:` - for documentation update\n\nSometimes commit can have several responsibilities. As example: when you write\ndocumentation, test and implementation for a feature in the one commit. You can do\nextra effort to split and rearrange commits to make it atomic. But does it\nreally provide significant value if we already have a strong convention for\nchangelog (see the next section)?\n\nSo, when you in such situation use the first applicable prefix in the list:\nbetween `docs` and `refactor` - pick `refactor`.\n\nAlso, there is one more special prefix for release commits. Release commit\nmessages **must** look like: `release: v0.4.0`.\n\n### Changelog\n\nStarting from `v0.4.0` [keep a changelog](https://keepachangelog.com/en/1.0.0/)\nguideline must be met.\n\nIf you adding something - provide some lines to the unreleased section of the `CHANGELOG.md`.\n\n### Versioning\n\nThe project strictly follows [SemVer](https://semver.org/spec/v2.0.0.html).\n\nAfter `v1.0.0` even smallest backward incompatible change will bump major\nversion. _No exceptions._\n\nCommit with a version bump should contain _only_ version bump and CHANGELOG.md update.\n\n### GitHub Flow\n\nSince `v0.4.0` this repo strictly follow [GitHub\nFlow](https://guides.github.com/introduction/flow/) with some additions:\n\n* branch naming using dash: `improved-contexts`\n* use [references to\n  issues](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)\n  in commit messages and make links to issues in CHANGELOG.md\n\n### Planned features for v1.0.0\n\n* validation framework\n* error reporting improvements\n* various plugins for SCP (tracing, benchmarking, logging, etc)\n* site with guides and conventions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubyonworld%2Fflows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frubyonworld%2Fflows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubyonworld%2Fflows/lists"}