Just to make the main idea of th state machine more clear I have a proposal to restrict the aasm_column setter at all, because it barely makes any sense, if we have events to transition from one state to another. This way it would have been very strict and clean, which is good - we won't need to think if we accidently assigned a new state, which could be very unwanted.
So, basically, it would look something like this (exampe):
@user = User.new
@user.state # sleeping (Why so ? Please see my pull request for this one: alto#9)
@user.state = :run # Some TransitionException exception thrown - "Direct assignment is not allowed"
@user.sleeping? # true. No state change.
@user.run! # => true. Changing states only by using events
@user.running? # true. New state is active
I think it makes more sense to do it that way.
From what I understand you want to use the bang method to force overrwriting the current state, even if your own rules (transitions) say you shouldn't. Is that right?
We currently have three suggestions how to use the bang method:
In fact the current solution (1) doesn't add any extra value to classes which are not persisted (using ActiveRecord or Mongoid). All three solutions have their relevance and make sense to me. That's a tough decision.
Does anyone have any good arguments for or against one of them?
I just had an idea, to use only the event method (bang or ordinary method) calls: run!, sleep!, etc just to switch from state to state. And to restrict direct assignment.
By the way. Using NON-bang methods doesn't make any sense too. The only application I see for it - is to perform transitions without exceptions.
And one more idea - Not to perform any transitions if the record is new:
@user = User.new
@user.new_record? # => true
@user.state # => "sleeping"
@user.run! # => TransitionException. "Record must be persisted before performing any transitions."
@user.run # => false. Record is not persisted.
That way it is extremely strict and hence - straightforward. Initial state cannot be skipped that way and must be persisted to the Database.
So, you would argue in favor of suggestion 2 then? Obviously nobody else has a take in this issue. Thus we are free to decide ;)
I think we should make this configurable. See #87 for "Slop mode" which would allow direct assignment and pick the first event which matches.
Sorry for getting back to this issue so late. Interestingly, after reading it again now, I recognised that I got it wrong right from the start. Only thing you suggested is this Direct assignment is not allowed thing, which I fully support. Will do this for AASM version 4.
Nice to hear :) Good luck. Looking forward to get a new version :)
This sounds like the issue I described here
I noticed a few specs in my project using update_attribute which would negate any event transition. I think this in combination with pull request #95 would help ensure models are always in valid states.
Working on this now. I recently saw somebody using direct assignment in order to let users interactively select the to-be-state. This is ambiguous and confusing (from a technical point of view), but still developers may choose to do so. I'm now thinking about making it configurable, and allowing direct-assignment by default.
@unabl4 Are you using ActiveRecord with this?
I assume you do.
may configure to not allow direct assignment for persisted AASM models …
Take a look at the aasm4 feature branch. :)