Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update_current_state doesn't trigger state events #69

Closed
simonc opened this issue Jan 18, 2013 · 6 comments
Closed

update_current_state doesn't trigger state events #69

simonc opened this issue Jan 18, 2013 · 6 comments

Comments

@simonc
Copy link

simonc commented Jan 18, 2013

Since state events like :enter and :exit are triggered in fire_event it is not possible to manually set the state and enjoy the callbacks at the same time.

I'd like to be able to set the state in a virtual attribute and still have the callbacks triggered.

@troessner
Copy link
Owner

Not sure I follow 100% - you want something like:

self.state = :foobar
save!

to trigger whatever is defined via e.g. on_transition, am I understanding this correctly?

@simonc
Copy link
Author

simonc commented Jan 20, 2013

If I define the following:

class Product
  include ActiveModel::Transitions

  state_machine do
    state :available
    state :out_of_stock, :enter => :enter_out_of_stock
  end
end

I expect product.update_current_state(:out_of_stock) to trigger enter_out_of_stock.
I think this one at least would make sense.

On the other hand, having the same behavior with product.state = :out_of_stock would be nice but I understand it may break some things...

@troessner
Copy link
Owner

Ah, ok, now I see what you mean. Well, the thing is, the transition methods are the canonical way to go from one state to another including callbacks and what not. I would not expect a manual state change to trigger additional action besides the state change, that's why we have dedicated methods for this.

Unless you have some really good use cases where this makes sense I'm afraid I don't see the point in this.

@simonc
Copy link
Author

simonc commented Jan 22, 2013

I know that the transition should be the way to go but here is my use case:

It's a prospects managing tool. Users can change the status of a prospect themselves. This means that I have to provide a select entry with the states list and they can pick any of them without any constraints.

In some cases, I need some actions done before or after the state change. I could create a transition for each state, have a virtual attribute with some kind of transition detection to call the right one but I would have to make one transition for each state and at that point I should probably forget the state machine...

Maybe you'll not see this as a use case or maybe I missed something or some concept ^^

@troessner
Copy link
Owner

Yes, I know that use case - had that one myself before.
The solution we came up with was pretty straight forward and simple:

Say, for the sake of simplicity, you are on a page where you can set the state for a record via dropdown menu (you can easily get all available states of the state machine, see the README). Now you just define a hash on the server side which maps those state names to the corresponding transitions. On form submit, you do something like this in pseudo code:

STATE_TO_TRANSITION = {
  my_state: :my_method
}

def my_action
  @my_object.send STATE_TO_TRANSITION[params[:my_object][:state_name]]
end

If you totally trust your users (e.g. if it's an admin interface) you can also just render the transitions in the dropdown itself, then you don't even need something like that hash from above.

@simonc
Copy link
Author

simonc commented Jan 22, 2013

I see what you mean. I can trust the users, it's a inner-company tool and it's ok.
But like I said, in that case I have to define a transition for each state.
I could use metaprog to iterate over each state and create a set_as_#{state} method.

The only thing I fear is losing readability, especially in the controller.
Thanks for your help. I'll close the issue and try to work around all this ;)

@simonc simonc closed this as completed Jan 22, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants