Cast string to symbol in fire/fire!, and fix deceptive error class and message (#788)

* Cast string to sym when checking event in `fire`

* Return early from method if event found

* Change message to reference Event, not State

* Add UndefinedEvent exception

Previously the code raised "UndefinedState" when it failed to find an
Event. This is confusing but was already released to the public. So this
adds UndefinedEvent as a subclass of UndefinedState and raises it
instead.

* Update Changelog
This commit is contained in:
Norman Clarke 2022-07-27 06:58:17 -03:00 committed by GitHub
parent 7a351ecd8a
commit bf7ff4c44a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 15 deletions

View File

@ -2,6 +2,9 @@
## unreleased
* Allow `fire` and `fire!` to accept a String or Symbol for the event name, and raise AASM::UndefinedEvent rather than AASM::UndefinedState
when an event can not be found, thanks to [norman](https://github.com/norman).
## 5.3.0
* Add Ruby 3.1 and Rails 7 to the CI matrix [#775](https://github.com/aasm/aasm/pull/775), thanks to [petergoldstein](https://github.com/petergoldstein)

View File

@ -17,5 +17,6 @@ module AASM
end
class UndefinedState < RuntimeError; end
class UndefinedEvent < UndefinedState; end
class NoDirectAssignmentError < RuntimeError; end
end

View File

@ -134,10 +134,11 @@ module AASM
private
def event_exists?(event_name, bang = false)
event = @instance.class.aasm(@name).state_machine.events[event_name]
event_error = bang ? "#{event_name}!" : event_name
event = @instance.class.aasm(@name).state_machine.events[event_name.to_sym]
return true if event
raise AASM::UndefinedState, "State :#{event_error} doesn't exist" if event.nil?
event_error = bang ? "#{event_name}!" : event_name
raise AASM::UndefinedEvent, "Event :#{event_error} doesn't exist" if event.nil?
end
end
end

View File

@ -153,11 +153,11 @@ describe 'callbacks for the new DSL' do
expect {
callback.aasm.fire(:unknown)
}.to raise_error(AASM::UndefinedState, "State :unknown doesn't exist")
}.to raise_error(AASM::UndefinedEvent, "Event :unknown doesn't exist")
expect {
callback.aasm.fire!(:unknown)
}.to raise_error(AASM::UndefinedState, "State :unknown! doesn't exist")
}.to raise_error(AASM::UndefinedEvent, "Event :unknown! doesn't exist")
end
it "does not run any state callback if the event guard fails" do

View File

@ -92,10 +92,10 @@ describe 'when being unsuspended' do
end
it "should raise AASM::UndefinedState when firing unknown events" do
expect { auth.aasm.fire(:unknown) }.to raise_error(AASM::UndefinedState, "State :unknown doesn't exist")
expect { auth.aasm.fire(:unknown) }.to raise_error(AASM::UndefinedEvent, "Event :unknown doesn't exist")
end
it "should raise AASM::UndefinedState when firing unknown bang events" do
expect { auth.aasm.fire!(:unknown) }.to raise_error(AASM::UndefinedState, "State :unknown! doesn't exist")
expect { auth.aasm.fire!(:unknown) }.to raise_error(AASM::UndefinedEvent, "Event :unknown! doesn't exist")
end
end

View File

@ -296,15 +296,32 @@ describe 'current event' do
end
describe "when calling events with fire/fire!" do
it "fire should populate aasm.current_event and transition (sleeping to showering)" do
pe.aasm.fire(:wakeup)
expect(pe.aasm.current_event).to eq :wakeup
expect(pe.aasm.current_state).to eq :showering
context "fire" do
it "should populate aasm.current_event and transition (sleeping to showering)" do
pe.aasm.fire(:wakeup)
expect(pe.aasm.current_event).to eq :wakeup
expect(pe.aasm.current_state).to eq :showering
end
it "should allow event names as strings" do
pe.aasm.fire("wakeup")
expect(pe.aasm.current_event).to eq :wakeup
expect(pe.aasm.current_state).to eq :showering
end
end
it "fire! should populate aasm.current_event and transition (sleeping to showering)" do
pe.aasm.fire!(:wakeup)
expect(pe.aasm.current_event).to eq :wakeup!
expect(pe.aasm.current_state).to eq :showering
context "fire!" do
it "should populate aasm.current_event and transition (sleeping to showering)" do
pe.aasm.fire!(:wakeup)
expect(pe.aasm.current_event).to eq :wakeup!
expect(pe.aasm.current_state).to eq :showering
end
it "should allow event names as strings" do
pe.aasm.fire!("wakeup")
expect(pe.aasm.current_event).to eq :wakeup!
expect(pe.aasm.current_state).to eq :showering
end
end
end
end