From 6387036bf91397cd6203cc7c279d8c7b76020771 Mon Sep 17 00:00:00 2001 From: Benedikt Deicke Date: Wed, 18 Jul 2018 14:51:40 +0200 Subject: [PATCH] Make sure attributes are updated before calling callbacks --- lib/active_record_upsert/active_record/persistence.rb | 5 ++--- spec/active_record/base_spec.rb | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/active_record_upsert/active_record/persistence.rb b/lib/active_record_upsert/active_record/persistence.rb index 5316b05..c903542 100644 --- a/lib/active_record_upsert/active_record/persistence.rb +++ b/lib/active_record_upsert/active_record/persistence.rb @@ -5,7 +5,7 @@ def upsert!(attributes: nil, arel_condition: nil, validate: true) raise ::ActiveRecord::ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly? raise ::ActiveRecord::RecordSavedError, "Can't upsert a record that has already been saved" if persisted? validate == false || perform_validations || raise_validation_error - values = run_callbacks(:save) { + run_callbacks(:save) { run_callbacks(:create) { attributes ||= changed attributes = attributes + @@ -15,8 +15,6 @@ def upsert!(attributes: nil, arel_condition: nil, validate: true) } } - @attributes = self.class.attributes_builder.build_from_database(values.first.to_h) - self end @@ -29,6 +27,7 @@ def upsert(*args) def _upsert_record(upsert_attribute_names = changed, arel_condition = nil) existing_attributes = attributes_with_values_for_create(self.attributes.keys) values = self.class._upsert_record(existing_attributes, upsert_attribute_names, [arel_condition].compact) + @attributes = self.class.attributes_builder.build_from_database(values.first.to_h) @new_record = false values end diff --git a/spec/active_record/base_spec.rb b/spec/active_record/base_spec.rb index 58f88e7..187845e 100644 --- a/spec/active_record/base_spec.rb +++ b/spec/active_record/base_spec.rb @@ -11,6 +11,16 @@ module ActiveRecord record.upsert end + it 'updates the attribute before calling after callbacks' do + MyRecord.create(id: 'some_id', name: 'Some name') + + allow(record).to receive(:after_s) { expect(record.name).to eq('Some name') } + allow(record).to receive(:after_c) { expect(record.name).to eq('Some name') } + allow(record).to receive(:after_com) { expect(record.name).to eq('Some name') } + + record.upsert + end + context 'when the record does not exist' do it 'sets timestamps' do record.upsert