views:

99

answers:

3

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?

A: 

Are you looking for something like Finite State Machine?

http://slagyr.github.com/statemachine/

Tam
+1  A: 

Try Ruote. It is a full fledged work-flow engine built on top of Ruby.

Documentation:

Ruote Documentation page 1

Ruote Documentation page 2

Creating a Ruote Process

KandadaBoggu
I think it is spelled "Ruote". Not the smartest of the names - I wonder how many people have made the same mistake as you.
egarcia
Thanks for that. Fixed the typo.
KandadaBoggu
Dear egarcia,if you translate "ruote" from italian to spanish you get "ruedas", "wheels". The pun is intended, as some people think workflow in terms of routes while other think in terms of vehicle (where to go versus can go).I could say the gem "workflow" has a poor name (it's a state machine library and not really workflow specific) and say the authors are not smart, but I won't allow myself such simplifications.Best regards.
jmettraux
Well, no one has misspelled workflow's name yet :). I wasn't implying that the authors were not smart - I was questioning one particular decision.
egarcia
Well then, wrokflow ;-)
jmettraux
Both Ruote and Workflow seem interesting, but neither seem to have provisions for creating a new workflow defined by the end user.
midas06
I'm sure Workflow can (egarcia will probably help). Ruote definitely can (http://gist.github.com/371087 for example).
jmettraux
Naming sure caused me trouble when I was googling the gem. I was searching for Ruote and Rails. I got lots of results for Rails Routing instead of Rails and Ruote.. :-)
KandadaBoggu
Ruote does support defining workflows by user.
KandadaBoggu
Jmettraux, I see your example, but im new to ruby and don't see how that solves my problem. Any chance you could post a more detailed response as a separate answer (i think the discussion is being hidden in the comments). KandadaBoggu, do you have an example somewhere?
midas06
Updated the answer with links to the documentation.
KandadaBoggu
Midas06, if you're new to Ruby, I don't want to bother you anymore with ruote. Teach yourself about ruby, look at state machine libraries and do your best. Write a small prototype, make small tries, they will teach you a lot.
jmettraux
A: 

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

egarcia