Skip to content

Commit

Permalink
Restores DIRTY changes information when updating an attribute with Ac…
Browse files Browse the repository at this point in the history
…tiveRecordPersistence
  • Loading branch information
KirtashW17 committed May 17, 2023
1 parent 2e952ff commit 29718c7
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 39 deletions.
3 changes: 2 additions & 1 deletion lib/aasm/persistence/active_record_persistence.rb
Expand Up @@ -88,7 +88,7 @@ def aasm_save
end

def aasm_update_column(attribute_name, value)
self.class.unscoped.where(self.class.primary_key => self.id).update_all(attribute_name => value) == 1
self.persisted? && self.update_column(attribute_name, value)
end

def aasm_read_attribute(name)
Expand All @@ -99,6 +99,7 @@ def aasm_write_attribute(name, value)
write_attribute(name, value)
end


def aasm_transaction(requires_new, requires_lock)
self.class.transaction(:requires_new => requires_new) do
lock!(requires_lock) if requires_lock
Expand Down
2 changes: 1 addition & 1 deletion lib/aasm/persistence/orm.rb
Expand Up @@ -16,11 +16,11 @@ module ORM
def aasm_write_state(state, name=:default)
attribute_name = self.class.aasm(name).attribute_name
old_value = aasm_read_attribute(attribute_name)
aasm_write_state_attribute state, name

success = if aasm_skipping_validations(name)
aasm_update_column(attribute_name, aasm_raw_attribute_value(state, name))
else
aasm_write_state_attribute state, name
aasm_save
end

Expand Down
13 changes: 3 additions & 10 deletions spec/unit/persistence/active_record_persistence_multiple_spec.rb
Expand Up @@ -152,17 +152,10 @@
end

it "passes state code instead of state symbol to update_all" do
# stub_chain does not allow us to give expectations on call
# parameters in the middle of the chain, so we need to use
# intermediate object instead.
obj = double(Object, update_all: 1)
allow(MultipleGate).to receive_message_chain(:unscoped, :where)
.and_return(obj)

allow(gate).to receive(:update_column).and_return(true)
allow(gate).to receive(:persisted?).and_return(true)
gate.aasm_write_state state_sym, :left

expect(obj).to have_received(:update_all)
.with(Hash[gate.class.aasm(:left).attribute_name, state_code])
expect(gate).to have_received(:update_column).with(gate.class.aasm(:left).attribute_name, state_code)
end
end

Expand Down
38 changes: 11 additions & 27 deletions spec/unit/persistence/active_record_persistence_spec.rb
Expand Up @@ -152,36 +152,12 @@
end

it "passes state code instead of state symbol to update_all" do
# stub_chain does not allow us to give expectations on call
# parameters in the middle of the chain, so we need to use
# intermediate object instead.
obj = double(Object, update_all: 1)
allow(Gate).to receive_message_chain(:unscoped, :where).and_return(obj)

allow(gate).to receive(:update_column).and_return(true)
allow(gate).to receive(:persisted?).and_return(true)
gate.aasm_write_state state_sym

expect(obj).to have_received(:update_all)
.with(Hash[gate.class.aasm.attribute_name, state_code])
expect(gate).to have_received(:update_column).with(gate.class.aasm.attribute_name, state_code)
end

it "searches model outside of default_scope when update_all" do
# stub_chain does not allow us to give expectations on call
# parameters in the middle of the chain, so we need to use
# intermediate object instead.
unscoped = double(Object, update_all: 1)
scoped = double(Object, update_all: 1)

allow(Gate).to receive(:unscoped).and_return(unscoped)
allow(Gate).to receive(:where).and_return(scoped)
allow(unscoped).to receive(:where).and_return(unscoped)

gate.aasm_write_state state_sym

expect(unscoped).to have_received(:update_all)
.with(Hash[gate.class.aasm.attribute_name, state_code])
expect(scoped).to_not have_received(:update_all)
.with(Hash[gate.class.aasm.attribute_name, state_code])
end
end

context "when AASM is not skipping validations" do
Expand Down Expand Up @@ -489,6 +465,14 @@
expect(persistor).not_to be_sleeping
end

it 'should restore DIRTY changes information when updating an attribute' do
object = InvalidPersistor.create(name: 'name')
expect(object).to be_sleeping
object.run!
expect(object).to be_running
expect(object.changes).not_to have_key(:status)
end

describe 'pessimistic locking' do
let(:worker) { Worker.create!(:name => 'worker', :status => 'sleeping') }

Expand Down

0 comments on commit 29718c7

Please sign in to comment.