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

Restores DIRTY changes information when updating an attribute with ActiveRecordPersistence #824

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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