I'm interested in creating a system where the user can define the steps in a workflow. Is there a gem that already handles this? I thought about one of the state machine gems, but they all seem to be for pre-defined states. I've been thinking maybe i can use state machine for the individual step types... An email step could have a few states [New, Assigned, Done], and the workflow could just be lists of these stateful steps. Are there other solutions out there?
Try Ruote. It is a full fledged work-flow engine built on top of Ruby.
Documentation:
For state machine let me suggest another one: workflow
The reason why all the gems use "pre-defined" states is because generally there's some ruby code involved with states: you say things like "when a transition from this state to this state happens, execute this code" or "before transitioning from here to there, check this ruby guard". This kind of functionality can't be implemented if the states are not somewhat "hard-coded".
If you just need a text field, without any code being executed at no point, you can just use a simple "State" model, containing:
- A name (string)
- The user_id that created this state (or a group_id if you are using something more sophisticated)
- The model this state is for. This could be either an integer or a string, depending on your tastes.
- The state parent_id (can be null). Typically, acts_as_tree will help you with this one.
Assuming that you use a user_id and a string for the model, then the state drop down for an email would be populated like this:
@states = State.find(:conditions => {
:user_id => current_user.id,
:model_name => 'State',
:parent_id => 4 #so you get the possible states that follow "New"
})
If you do need to execute some code at some transition/guard, you will need to use predefined states. It's also possible, but you would have to change your requirements a bit: instead of letting users define their own states, you would leave them "activate" some of them from a list. Then, the "user has activated this state" would be just another "guard" on your state system.
EDIT: Added the parent_id and acts_as_tree reference