Skip to content

Loading…

AASM column attribute direct assignment restriction #53

Closed
unabl4 opened this Issue · 12 comments

4 participants

@unabl4

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.

@alto alto was assigned
@alto
aasm member

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?

@alto
aasm member

We currently have three suggestions how to use the bang method:

  1. immediately save the state to the database (that's currently in use)
  2. throw an exception if the state transition fails
  3. force the requested state

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?

@unabl4

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.

@alto
aasm member

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 ;)

@johnnyshields

I think we should make this configurable. See #87 for "Slop mode" which would allow direct assignment and pick the first event which matches.

@alto
aasm member

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. :+1:

@unabl4

Nice to hear :) Good luck. Looking forward to get a new version :)

@jspooner

This sounds like the issue I described here
#95 (comment)

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.

@alto
aasm member

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.

@alto
aasm member

@unabl4 Are you using ActiveRecord with this?

@alto
aasm member

I assume you do.

@alto
aasm member

Take a look at the aasm4 feature branch. :)

@alto alto closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.