benzelano / test_lh_import

1 stars 0 forks source link

State events don't call event methods #130

Closed benzelano closed 13 years ago

benzelano commented 13 years ago

Aaron Pfeifer opened this issue

When you use a state event and you’ve overridden the event method, the method won’t get called. For example,

class Vehicle < ActiveRecord::Base
  state_machine :initial => :parked do
    event :ignite do
      transition :parked => :idling
    end
  end

  def ignite(*args)
    raise ArgumentError # Never gets called
  end
end

v = Vehicle.new(:state_event => &rsquo;ignite&rsquo;)
v.save

This transitions the object, but never calls #ignite which is unexpected.

original LH ticket

This ticket has 1 attachment(s).

benzelano commented 13 years ago
benzelano commented 13 years ago

This is basically not going to get fixed until there’s a decent, clean solution which I don’t have right now.

benzelano commented 13 years ago

Fixed with implementing the example using around_transitions:

@@@ ruby class Vehicle < ActiveRecord::Base state_machine :initial => :parked do around_transition :on => :ignite do |vehicle, transition, block| raise ArgumentError end

event :ignite do
  transition :parked => :idling
end

end end

v = Vehicle.new(:state_event => ’ignite’) v.save # => ArgumentError: ArgumentError @@@

benzelano commented 13 years ago

Gareth Adams commented

Is there any case where before_transition etc. shouldn’t be used?

Given the error displayed in this ticket, it seems like overriding the event method is never a better idea than using a *_transition callback.

With that in mind I’ve had a go at improving the documentation to warn where this problem might occur. It’s attached as a patch and also sent as a Github pull request (I don’t know which you preferred)

benzelano commented 13 years ago

While I think there are recommended implementation paths, I don’t think these are absolutes. Off the top of my head, the biggest potential win with overriding event methods comes when you start dealing with inheritance.

There is also a slight difference in the order of execution. When you’re in an around_transition, the transition has already been deemed valid. On the other hand, if you override the event method, you’re able to make changes to the object before state_machine even checks if that event is valid.

I’m sure there are various use cases that folks have that utilize both of the behaviors above. It may very well be the case that overriding events is less common.

I’ll take a look at the doc updates. Thanks for sharing that patch.