Skip to content

Commit

Permalink
Merge pull request #142 from wata727/force_updated
Browse files Browse the repository at this point in the history
Add `previously_force_updated?`
  • Loading branch information
wata727 authored Aug 7, 2023
2 parents 02145fc + ca269d5 commit b9763b1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
6 changes: 6 additions & 0 deletions lib/activerecord-bitemporal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ def id_in_database
swapped_id.presence || super
end

def previously_force_updated?
@previously_force_updated
end

def valid_from_cannot_be_greater_equal_than_valid_to
if valid_from && valid_to && valid_from >= valid_to
errors.add(:valid_from, "can't be greater equal than valid_to")
Expand Down Expand Up @@ -141,10 +145,12 @@ def bitemporalize(
# MEMO: #update_columns is not call #_update_row (and validations, callbacks)
update_columns(bitemporal_id_key => swapped_id) unless send(bitemporal_id_key)
swap_id!(without_clear_changes_information: true)
@previously_force_updated = false
end

after_find do
self.swap_id! if self.send(bitemporal_id_key).present?
@previously_force_updated = false
end

# Callback hook to `validates :xxx, uniqueness: true`
Expand Down
8 changes: 7 additions & 1 deletion lib/activerecord-bitemporal/bitemporal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,12 +277,13 @@ def update_transaction_to(value)
end

refine ActiveRecord::Base do
# MEMO: Do not copy `swapped_id`
# MEMO: Do not copy bitemporal internal status
def dup(*)
super.tap { |itself|
itself.instance_exec do
@_swapped_id_previously_was = nil
@_swapped_id = nil
@previously_force_updated = false
end unless itself.frozen?
}
end
Expand Down Expand Up @@ -320,6 +321,7 @@ def _update_row(attribute_names, attempted_action = 'update')
before_instance&.save_without_bitemporal_callbacks!(validate: false)
# NOTE: after_instance always exists
after_instance.save_without_bitemporal_callbacks!(validate: false)
@previously_force_updated = self.force_update?

# update 後に新しく生成したインスタンスのデータを移行する
@_swapped_id_previously_was = swapped_id
Expand All @@ -345,6 +347,7 @@ def destroy(force_delete: false, operated_at: Time.current)
@destroyed = false
_run_destroy_callbacks {
@destroyed = update_transaction_to(operated_at)
@previously_force_updated = force_update?

# force_update の場合は削除時の状態の履歴を残さない
unless force_update?
Expand Down Expand Up @@ -397,6 +400,7 @@ def reload(options = nil)
# NOTE: Hook to copying swapped_id
@_swapped_id_previously_was = nil
@_swapped_id = fresh_object.swapped_id
@previously_force_updated = false
self
end
elsif Gem::Version.new("6.1.0") <= ActiveRecord.version
Expand All @@ -420,6 +424,7 @@ def reload(options = nil)
# NOTE: Hook to copying swapped_id
@_swapped_id_previously_was = nil
@_swapped_id = fresh_object.swapped_id
@previously_force_updated = false
self
end
else
Expand All @@ -442,6 +447,7 @@ def reload(options = nil)
# NOTE: Hook to copying swapped_id
@_swapped_id_previously_was = nil
@_swapped_id = fresh_object.swapped_id
@previously_force_updated = false
self
end
end
Expand Down
23 changes: 22 additions & 1 deletion spec/activerecord-bitemporal/bitemporal_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"valid_from" => [nil, be_present],
"valid_to" => [nil, ActiveRecord::Bitemporal::DEFAULT_VALID_TO],
"name" => [nil, "Tom"]
)
),
previously_force_updated?: false
)
}
end
Expand Down Expand Up @@ -918,6 +919,7 @@ def employee.wrapped_name
it { expect { subject }.not_to change(employee, :id) }
it { expect { subject }.to change(employee, :swapped_id).from(swapped_id).to(kind_of(Integer)) }
it { expect { subject }.to change(employee, :swapped_id_previously_was).from(nil).to(swapped_id) }
it { expect { subject }.to change(employee, :previously_force_updated?).from(false).to(true) }

context "with `#valid_at`" do
let!(:employee) { Timecop.freeze("2019/1/1") { Employee.create!(name: "Jane") } }
Expand Down Expand Up @@ -1215,6 +1217,7 @@ class EmployeeWithUniquness < Employee
it { expect { subject }.not_to change { Employee.ignore_valid_datetime.within_deleted.count } }
it { expect { subject }.not_to change(employee, :swapped_id) }
it { expect { subject }.not_to change(employee, :swapped_id_previously_was) }
it { expect { subject }.to change(employee, :previously_force_updated?).from(false).to(true) }
it { expect(subject).to eq employee }
end
end
Expand Down Expand Up @@ -2723,6 +2726,24 @@ class EmployeeWithUniquness < Employee
end
end

describe "#previously_force_updated?" do
let(:employee) { Employee.create!(name: "Jone") }

it "sets previously_force_updated after find" do
expect(Employee.find(employee.id)).not_to be_previously_force_updated
end

it "reverts the previously_force_updated after updating" do
employee.force_update { |e| e.update!(name: "Tom") }
expect { employee.update!(name: "Kevin") }.to change(employee, :previously_force_updated?).from(true).to(false)
end

it "reverts the previously_force_updated after reloading" do
employee.force_update { |e| e.update!(name: "Tom") }
expect { employee.reload }.to change(employee, :previously_force_updated?).from(true).to(false)
end
end

describe "ActiveRecord" do
context "[Bug fix] https://github.com/rails/rails/pull/38583 in Rails 5.x" do
it { expect { Employee.where(Arel.sql("name").eq("Tom")).except_bitemporal_default_scope.to_sql }.not_to raise_error }
Expand Down

0 comments on commit b9763b1

Please sign in to comment.