I’ve been using the two awesome gems, state_machine and cancan recently in my rails application but I’m curious as to the best way to integrate them cleanly.
Currently I’ve placed state transitions on buttons that go on actions authorized by the controller. This works perfectly, I can restrict who can perform that action.
I would like to give the user the ability to change the objects state in the edit form as well. I’ve noticed that state_machine will pick up on the state_event key in the hash, with the value of the action to perform (so it will go through all of state_machines callbacks).
This can be passed in with the params hash in update_attributes. Fantastic.
However only certain users should be able to change the object to certain states. How would I implement this?. The idea is that
params['state_event']=='move_to_x'
Should bail out for some users but be allowed for others. It also concerns me as until I implement this is the authorization part a clever user could post anything inside state event, even if they shouldn’t be allowed too!.
This wasn’t actually as terrible as I thought, and I’ve done it in a way that keeps the code rather short and current_user out of my models (so big plus).
The trick was to call authorize again in the controller.
basically
This way I can just aliases in Ability.rb. So users that can do the action will be authorized, and users that cannot will get the exception. This is also awesome as it’s the same ability I’ll be using on the button based actions.
The only caveat, is that you can’t use @object.state_transistions to get a list of the available states the user can transition to, but it should be possible to do this via some sort of helper method.
UPDATE: though getting those states in a view like layer is easy enough
i’m using simple form so I just a collection input such that
Which leaves the select with all the transistions the object can go through, and that the user is also authorized to do :).