{"id":13878933,"url":"https://github.com/leastbad/all_futures","last_synced_at":"2025-09-17T23:08:59.912Z","repository":{"id":41140699,"uuid":"359503266","full_name":"leastbad/all_futures","owner":"leastbad","description":"A Redis ORM for reactive applications. Quacks just like Active Record. 🦆","archived":false,"fork":false,"pushed_at":"2022-05-11T04:31:38.000Z","size":248,"stargazers_count":97,"open_issues_count":3,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-09-13T09:20:48.074Z","etag":null,"topics":["activemodel","activerecord","rails","redis","stimulusreflex"],"latest_commit_sha":null,"homepage":"https://allfutures.leastbad.com","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/leastbad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-19T15:12:32.000Z","updated_at":"2025-01-22T23:38:22.000Z","dependencies_parsed_at":"2022-09-10T12:21:18.529Z","dependency_job_id":null,"html_url":"https://github.com/leastbad/all_futures","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/leastbad/all_futures","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leastbad%2Fall_futures","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leastbad%2Fall_futures/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leastbad%2Fall_futures/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leastbad%2Fall_futures/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leastbad","download_url":"https://codeload.github.com/leastbad/all_futures/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leastbad%2Fall_futures/sbom","scorecard":{"id":582161,"data":{"date":"2025-08-11","repo":{"name":"github.com/leastbad/all_futures","commit":"925d64740f9299b4c7d24b88543ca469685a0ccd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"65 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-4g8v-vg43-wpgf","Warn: Project is vulnerable to: GHSA-8xww-x3g3-6jcv","Warn: Project is vulnerable to: GHSA-fwhr-88qx-h9g7","Warn: Project is vulnerable to: GHSA-mm33-5vfq-3mm3","Warn: Project is vulnerable to: GHSA-p84v-45xj-wwqj","Warn: Project is vulnerable to: GHSA-vfg9-r3fq-jvx4","Warn: Project is vulnerable to: GHSA-vfm5-rmrh-j26v","Warn: Project is vulnerable to: GHSA-wh98-p28r-vrc9","Warn: Project is vulnerable to: GHSA-x76w-6vjr-8xgj","Warn: Project is vulnerable to: GHSA-ch3h-j2vf-95pv","Warn: Project is vulnerable to: GHSA-xp5h-f8jf-rc8q","Warn: Project is vulnerable to: GHSA-3hhc-qp5v-9p2j","Warn: Project is vulnerable to: GHSA-579w-22j4-4749","Warn: Project is vulnerable to: GHSA-76r7-hhxj-r776","Warn: Project is vulnerable to: GHSA-hq7p-j377-6v63","Warn: Project is vulnerable to: GHSA-cr5q-6q9f-rq6q","Warn: Project is vulnerable to: GHSA-j6gc-792m-qgm2","Warn: Project is vulnerable to: GHSA-pj73-v5mw-pm9j","Warn: Project is vulnerable to: GHSA-h2wm-p2vg-6pw4","Warn: Project is vulnerable to: GHSA-228g-948r-83gx","Warn: Project is vulnerable to: GHSA-3x8r-x6xp-q4vm","Warn: Project is vulnerable to: GHSA-486f-hjj9-9vhh","Warn: Project is vulnerable to: GHSA-2qc6-mcvw-92cw","Warn: Project is vulnerable to: GHSA-353f-x4gh-cqq8","Warn: Project is vulnerable to: GHSA-59gp-qqm7-cw4j","Warn: Project is vulnerable to: GHSA-5w6v-399v-w3cc","Warn: Project is vulnerable to: GHSA-cgx6-hpwq-fhv5","Warn: Project is vulnerable to: GHSA-crjr-9rc5-ghw8","Warn: Project is vulnerable to: GHSA-fq42-c5rg-92c2","Warn: Project is vulnerable to: GHSA-gx8x-g87m-h5q6","Warn: Project is vulnerable to: GHSA-jc36-42cf-vqwj","Warn: Project is vulnerable to: GHSA-mrxw-mxhj-p664","Warn: Project is vulnerable to: GHSA-pxvg-2qj5-37jq","Warn: Project is vulnerable to: GHSA-r95h-9x8f-r3f7","Warn: Project is vulnerable to: GHSA-v6gp-9mmm-c6p5","Warn: Project is vulnerable to: GHSA-vvfq-8hwr-qm4m","Warn: Project is vulnerable to: GHSA-xc9x-jj77-9p9j","Warn: Project is vulnerable to: GHSA-xh29-r2w5-wx8m","Warn: Project is vulnerable to: GHSA-xxx9-3xcr-gjj3","Warn: Project is vulnerable to: GHSA-22f2-v57c-j9cx","Warn: Project is vulnerable to: GHSA-3h57-hmj3-gj3p","Warn: Project is vulnerable to: GHSA-54rr-7fvw-6x8f","Warn: Project is vulnerable to: GHSA-65f5-mfpf-vfhj","Warn: Project is vulnerable to: GHSA-7g2v-jj9q-g3rg","Warn: Project is vulnerable to: GHSA-7wqh-767x-r66v","Warn: Project is vulnerable to: GHSA-8cgq-6mh2-7j6v","Warn: Project is vulnerable to: GHSA-93pm-5p5f-3ghx","Warn: Project is vulnerable to: GHSA-c6qg-cjj8-47qp","Warn: Project is vulnerable to: GHSA-gjh7-p2fx-99vx","Warn: Project is vulnerable to: GHSA-hxqx-xwvh-44m2","Warn: Project is vulnerable to: GHSA-rqv2-275x-2jq5","Warn: Project is vulnerable to: GHSA-vpfw-47h7-xj4g","Warn: Project is vulnerable to: GHSA-wq4h-7r42-5hrr","Warn: Project is vulnerable to: GHSA-xj5v-6v4g-jfw6","Warn: Project is vulnerable to: GHSA-5x79-w82f-gw8w","Warn: Project is vulnerable to: GHSA-9h9g-93gc-623h","Warn: Project is vulnerable to: GHSA-mcvf-2q2m-x72m","Warn: Project is vulnerable to: GHSA-pg8v-g4xq-hww9","Warn: Project is vulnerable to: GHSA-rrfc-7g8p-99q8","Warn: Project is vulnerable to: GHSA-2rxp-v6pw-ch6m","Warn: Project is vulnerable to: GHSA-4xqq-m2hx-25v8","Warn: Project is vulnerable to: GHSA-5866-49gr-22v4","Warn: Project is vulnerable to: GHSA-r55c-59qm-vjw6","Warn: Project is vulnerable to: GHSA-vg3r-rm7w-2xgh","Warn: Project is vulnerable to: GHSA-vmwr-mc7x-5vc3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T19:27:42.799Z","repository_id":41140699,"created_at":"2025-08-20T19:27:42.799Z","updated_at":"2025-08-20T19:27:42.799Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275680444,"owners_count":25508570,"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","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["activemodel","activerecord","rails","redis","stimulusreflex"],"created_at":"2024-08-06T08:02:04.592Z","updated_at":"2025-09-17T23:08:59.888Z","avatar_url":"https://github.com/leastbad.png","language":"Ruby","readme":"---\ndescription: A Redis ORM for reactive applications. Quacks just like Active Record. 🦆\n---\n\n# All Futures\n\nRails developers can use the [all\\_futures](https://github.com/leastbad/all\\_futures) gem to persist data **across multiple requests**. It leverages Redis to provide an ephemeral model that you can use just like an Active Record model.\n\nIt's perfect for building faceted search interfaces, multi-step forms, real-time input validation and persisting the display state of UI elements.\n\nTry a demo, here: 👉 [Beast Mode StimulusReflex](https://beastmode.leastbad.com) 👈\n\n[![GitHub stars](https://img.shields.io/github/stars/leastbad/all\\_futures?style=social)](https://github.com/leastbad/all\\_futures) [![GitHub forks](https://img.shields.io/github/forks/leastbad/all\\_futures?style=social)](https://github.com/leastbad/all\\_futures) [![Twitter follow](https://img.shields.io/twitter/follow/theleastbad?style=social)](https://twitter.com/theleastbad) [![Discord](https://img.shields.io/discord/629472241427415060)](https://discord.gg/stimulus-reflex)\n\n## Is All Futures for you?\n\nDo you ever find yourself:\n\n* building complex search interfaces\n* creating multi-stage data entry processes\n* frustrated by the limitations of classic form submission\n* wanting to save data even if the model is currently invalid\n* reinventing the wheel every time you need field validation\n* needing granular dirty checking and state management for every attribute\n\nIf you answered yes to any of the above... you are every Rails developer, and you're not crazy. This functionality has been a blind-spot in the framework for a long time.\n\nYes, All Futures is for **you**.\n\n## Why use All Futures?\n\nMany reactive UI concepts are a pain in the ass to implement using the classic Rails request/response pattern, which was created at a time before developers started using Ajax to update portions of a page. ActionController is amazing, but if a user interaction doesn't fit cleanly into a single form submission, the developer now has to maintain UI state across multiple atomic requests. Naturally, this leads to abuse of the session object and awkward hacks to validate and persist models.\n\n{% hint style=\"danger\" %}\nIn vanilla Rails, it's very difficult to incrementally save models that require the presence of multiple attributes to be valid.\n{% endhint %}\n\nThe combination of ActionCable and Turbo Drive creates a persistent Connection that blurs the line between session and request, forcing a new mental model that is poorly served by ActionDispatch and the conventions which drove Rails to success... in 2005.\n\nMoving forward, new tooling is required to take full advantage of reactive possibilities.\n\nAll Futures presents a flexible and lightweight mechanism to refine a model that persists its attributes across multiple updates, and even multiple servers.\n\n## Key features and advantages\n\n* A natural fit with [StimulusReflex](https://stimulusreflex.com), [Stimulus](https://stimulus.hotwired.dev), [Turbo Drive](https://turbo.hotwired.dev/handbook/drive) and [mrujs](https://mrujs.com)\n* No reliance on sessions, so it works across servers\n* Easy to learn, quick to implement\n* Supports model attributes with defaults, arrays and associations\n* Per-attribute dirty checking and state management with rollbacks\n* Remembers previous model state across multiple requests\n* Automatic versioning allows time travel views\n* Model validations, errors and associations\n* Can be added as attributes in your Active Record model classes\n* No more temporary database tables that need to be purged later\n\n## How does All Futures work?\n\nAll Futures is the fusion of [Active Entity](https://github.com/jasl/activeentity) and [Kredis](https://github.com/rails/kredis). It is similar to using a **properly juiced** [ActiveModel::Model](https://api.rubyonrails.org/classes/ActiveModel/Model.html), except that it has full support for [Attributes](https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute), including arrays and nested attributes. All Futures classes behave like Active Record model instances as much as possible.\n\n```ruby\nclass Example \u003c AllFutures::Base\n  attribute :name, :string\n  validates :name, presence: true\nend\n\nexample = Example.create\nexample.valid? # false\nexample.errors # @errors=[#\u003cActiveModel::Error attribute=name, type=blank, options={}\u003e]\n```\n\nUnlike an Active Record model, All Futures instances can persist their attributes even if the attributes are currently invalid. This design allows you to resolve any errors present, even if it takes several distinct operations to do so.\n\nOnce the state of your attributes is valid, you can pass the `attributes` from your All Futures model right into the constructor of a real Active Record model.\n\n{% hint style=\"danger\" %}\nAll Futures v1 persisted the attributes every time you set the value of an attribute using bracket notation. **This behavior has been removed.** An explicit `save` operation is now required to persist changes.\n{% endhint %}\n\n## Who makes this?\n\nFirst, All Futures wouldn't exist without [Active Entity](https://github.com/jasl/activeentity) and [Kredis](https://github.com/rails/kredis). Thank you, [Jun Jiang](https://twitter.com/jasl9187) and [Kasper Timm Hansen](https://twitter.com/kaspth).\n\nAll Futures was originally created by [leastbad](https://twitter.com/theleastbad), who continues to serve as the primary developer and writer of words. :wave:\n\nv2 welcomes pivotal contributions from key members of the [StimulusReflex](https://stimulusreflex.com) core and moderation teams. [Stephen Margheim](https://twitter.com/fractaledmind) heroically made sure that callbacks work as expected, _twice_. [Julian Rubisch](https://twitter.com/julian\\_rubisch) is the reason All Futures models are usually interchangeable with Active Record models. [Nate Hopkins](https://twitter.com/hopsoft/), [Marco Roth](https://twitter.com/marcoroth\\_) and [Konnor Rogers](https://twitter.com/rogerskonnor/) have been generous with their feedback and suggestions.\n\nWe realized that this library needed to exist and had a deep understanding of how it should work _only_ because we have spent years helping thousands of Rails developers figure out the right way to develop reactive UIs.\n\nAll Futures truly was born in fire. :fire::hammer:\n\n## Try it now\n\nYou can experiment with [Beast Mode StimulusReflex](https://beastmode.leastbad.com), a live demonstration of using All Futures to drill down into a tabular dataset, [**right now**](https://beastmode.leastbad.com). 👈\n\nThe Beast Mode [codebase](https://github.com/leastbad/beast\\_mode) [![GitHub stars](https://img.shields.io/github/stars/leastbad/beast\\_mode?style=social)](https://github.com/leastbad/beast\\_mode) [![GitHub forks](https://img.shields.io/github/forks/leastbad/beast\\_mode?style=social)](https://github.com/leastbad/beast\\_mode) is set up as a **template repo** which I recommend that you clone and experiment with.\n\nThe three key files are the [CustomerFilter](https://github.com/leastbad/beast\\_mode/blob/master/app/models/customer\\_filter.rb), the [Reflex](https://github.com/leastbad/beast\\_mode/blob/master/app/reflexes/customers\\_reflex.rb) and the [Model](https://github.com/leastbad/beast\\_mode/blob/master/app/models/customer.rb). You can read the tutorial post behind this example on my blog [here](https://leastbad.com/beast-mode/).\n\nAssuming you're running at least Ruby 2.7.3, Postgres and have Redis running on your system, you can just run `bin/setup` to install it, including migrations and the DB seed file.\n\n{% embed url=\"https://www.youtube.com/watch?v=Fbo21aWFbhQ\" %}\nREFRACT\n{% endembed %}\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleastbad%2Fall_futures","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleastbad%2Fall_futures","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleastbad%2Fall_futures/lists"}