{"id":16805440,"url":"https://github.com/dewski/progressive","last_synced_at":"2025-03-17T07:43:42.191Z","repository":{"id":11158834,"uuid":"13530338","full_name":"dewski/progressive","owner":"dewski","description":"A lightweight ActiveModel backed state machine.","archived":false,"fork":false,"pushed_at":"2016-07-04T20:51:59.000Z","size":12,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-23T16:53:50.798Z","etag":null,"topics":[],"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/dewski.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":"2013-10-12T22:45:20.000Z","updated_at":"2016-07-04T06:00:24.000Z","dependencies_parsed_at":"2022-08-28T20:01:06.611Z","dependency_job_id":null,"html_url":"https://github.com/dewski/progressive","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/dewski%2Fprogressive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dewski%2Fprogressive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dewski%2Fprogressive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dewski%2Fprogressive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dewski","download_url":"https://codeload.github.com/dewski/progressive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243996900,"owners_count":20380978,"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-10-13T09:48:13.961Z","updated_at":"2025-03-17T07:43:42.166Z","avatar_url":"https://github.com/dewski.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Progressive\n\nA simple ActiveModel backed state machine.\n\n## Why yet another state machine?\n\nYou may be asking why another state machine implementation? Well, first off YASM.\nSecond, most other implementations rely on class level attributes and make it\ndifficult for inheritance and the rare case when a subject will need to have\n_multiple_ states.\n\nIf you only need to have 1 state for a model, Progressive works fine for that too.\n\nProgressive interacts with the states and events for a model at an instance level,\nnot class level. There are no magic methods defined based on your states or events\nit relies on method missing so it's very interoperable.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'progressive'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install progressive\n\n## Usage\n\n### Defining states on the subject model:\n\n```ruby\nclass State \u003c Progressive::State\n\nend\n\nclass User \u003c ActiveRecord::Base\n  include Progression::Subject\n\n  has_many :states, :as =\u003e :subject, :dependent =\u003e :destroy\n\n  states do\n    state :pending do\n      event :potential\n    end\n\n    state :potential do\n      event :interview =\u003e :interviewing\n      event :archive =\u003e :archived\n    end\n\n    state :interviewing do\n      event :potential\n      event :archive =\u003e :archived\n      event :hire =\u003e :hired\n    end\n\n    state :hired\n  end\n\n  after_hire :user_rollup\n  before_interview :notify_creator\n\n  def user_rollup\n    # Do something\n  end\n\n  def notify_creator\n\n  end\nend\n```\n\n### Interfacing with the state\n\n```ruby\nactor = User.first\nuser = User.first\n\nstate = user.states.first\nstate.state # =\u003e 'pending'\nstate.default_state # =\u003e :pending\nstate.to(:archived, :actor =\u003e actor) # =\u003e false\nstate.to(:potential, :actor =\u003e actor) # =\u003e true\nstate.state # =\u003e 'potential'\nstate.specification # =\u003e Progressive::Specification\nstate.current_state # =\u003e Progressive::Specification::State\n```\n\n### Short circuiting an event\n\nSince Progressive uses the same ActiveModel callbacks you're familiar with in\nyour ActiveRecord models, you can short circuit the event just by returning\na falsey statement within each callback.\n\nYou can add a before or after callback for any event. To see which events you\nhave available just check the Progressive specification:\n\n```ruby\nVideo.specification.event_names # =\u003e [:converting, :publish]\n```\n\nExample:\n\n```ruby\nclass Video \u003c ActiveRecord::Base\n  include Progression::Subject\n\n  has_one :state, :as =\u003e :subject, :dependent =\u003e :destroy\n\n  states do\n    state :pending do\n      event :converting\n    end\n\n    state :converting do\n      event :publish =\u003e :published\n    end\n\n    state :published\n  end\n\n  before_converting :valid_file_size?\n\n  def valid_file_size?\n    file_size \u003c 1.gigabyte\n  end\nend\n\nvideo = Video.first\nvideo.file_size # =\u003e 2.gigabytes\nvideo.state # =\u003e :pending\nvideo.converting # =\u003e false\nvideo.state # =\u003e :pending\n```\n\n## Maintainers\n\n- [@dewski](/dewski)\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 'Add 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%2Fdewski%2Fprogressive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdewski%2Fprogressive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdewski%2Fprogressive/lists"}