Skip to content

Commit

Permalink
Fix #save! not firing event attributes properly in ActiveRecord integ…
Browse files Browse the repository at this point in the history
…rations [pluginaweek#22 state:resolved]
  • Loading branch information
obrie committed May 23, 2009
1 parent 0d20db4 commit b48bfc9
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rdoc
@@ -1,5 +1,6 @@
== master

* Fix #save! not firing event attributes properly in ActiveRecord integrations
* Fix log files being included in gems

== 0.7.3 / 2009-04-25
Expand Down
2 changes: 1 addition & 1 deletion lib/state_machine/integrations/active_record.rb
Expand Up @@ -327,7 +327,7 @@ def define_state_predicate

# Adds hooks into validation for automatically firing events
def define_action_helpers
if super && action == :save
if super(:create_or_update) && action == :save
@instance_helper_module.class_eval do
define_method(:valid?) do |*args|
self.class.state_machines.fire_attribute_events(self, :save, false) { super(*args) }
Expand Down
9 changes: 6 additions & 3 deletions lib/state_machine/machine.rb
Expand Up @@ -1268,18 +1268,21 @@ def define_event_helpers

# Adds helper methods for automatically firing events when an action
# is invoked
def define_action_helpers
def define_action_helpers(action_hook = self.action)
action = self.action
private_method = owner_class.private_method_defined?(action_hook)

if owner_class.method_defined?(action) && !owner_class.state_machines.any? {|attribute, machine| machine.action == action && machine != self}
if (owner_class.method_defined?(action_hook) || private_method) && !owner_class.state_machines.any? {|attribute, machine| machine.action == action && machine != self}
# Action is defined and hasn't already been overridden by another machine
@instance_helper_module.class_eval do
# Override the default action to invoke the before / after hooks
define_method(action) do |*args|
define_method(action_hook) do |*args|
value = nil
result = self.class.state_machines.fire_attribute_events(self, action) { value = super(*args) }
value.nil? ? result : value
end

private action_hook if private_method
end

true
Expand Down
49 changes: 49 additions & 0 deletions test/unit/integrations/active_record_test.rb
Expand Up @@ -662,6 +662,55 @@ def test_should_not_run_after_callbacks
end
end

class MachineWithEventAttributesOnSaveBangTest < ActiveRecord::TestCase
def setup
@model = new_model
@machine = StateMachine::Machine.new(@model)
@machine.event :ignite do
transition :parked => :idling
end

@record = @model.new
@record.state = 'parked'
@record.state_event = 'ignite'
end

def test_should_fail_if_event_is_invalid
@record.state_event = 'invalid'
assert_raise(ActiveRecord::RecordInvalid) { @record.save! }
end

def test_should_fail_if_event_has_no_transition
@record.state = 'idling'
assert_raise(ActiveRecord::RecordInvalid) { @record.save! }
end

def test_should_be_successful_if_event_has_transition
assert @record.save!
end

def test_should_run_before_callbacks
ran_callback = false
@machine.before_transition { ran_callback = true }

@record.save!
assert ran_callback
end

def test_should_persist_new_state
@record.save!
assert_equal 'idling', @record.state
end

def test_should_run_after_callbacks
ran_callback = false
@machine.after_transition { ran_callback = true }

@record.save!
assert ran_callback
end
end

class MachineWithObserversTest < ActiveRecord::TestCase
def setup
@model = new_model
Expand Down

0 comments on commit b48bfc9

Please sign in to comment.