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

Exclude record valid range end in uniqueness validation #184

Merged
merged 1 commit into from
Jan 9, 2025

Conversation

wata727
Copy link
Contributor

@wata727 wata727 commented Dec 23, 2024

ActiveRecord::Bitemporal::Uniqueness#scope_relation validates that a record is unique over the valid period of the record being added. For example, if valid_from is 2024-03-01 and valid_datetime is 2024-06-01, the period to be validated will be from 2024-06-01 to 9999-12-31.

                       2024-03-01             2024-06-01                9999-12-31
                            |----------------------|----------------------|
                       valid_from           valid_datetime

                                                   <---------------------->

On the other hand, if the valid_datetime is earlier than the valid_from (e.g. 2024-01-01), the following period is validated:

2024-01-01             2024-03-01             2024-06-01                9999-12-31
                            |---------------------------------------------|
                       valid_from

     <---------------------->

In this case the range is calculated as follows:

# レコードを更新する時に valid_datetime が valid_from ~ valid_to の範囲外だった場合、
# 一番近い未来の履歴レコードを参照して更新する
# という仕様があるため、それを考慮して valid_to を設定する
if (record_valid_time && (record.valid_from..record.valid_to).cover?(record_valid_time)) == false && (record.persisted?)
finder_class.ignore_valid_datetime.where(bitemporal_id: record.bitemporal_id).valid_from_gt(target_datetime).order(valid_from: :asc).first.valid_from
else
valid_to
end

In principle this should be the same as the actual update logic, but it's not an exact match. The corresponding logic is as follows:

# 対象基準日において有効なレコード
# NOTE: 論理削除対象
current_valid_record = self.class.find_at_time(target_datetime, self.id)&.tap { |record|

# 有効なレコードがない場合
else
# 一番近い未来にある Instance を取ってきて、その valid_from を valid_to に入れる
nearest_instance = self.class.where(bitemporal_id: bitemporal_id).valid_from_gt(target_datetime).ignore_valid_datetime.order(valid_from: :asc).first

Since the find_at_time adds the WHERE valid_from <= valid_datetime AND valid_to > valid_datetime, it is correct to use ... rather than .. to see whether valid_datetime is included in the valid period.

Excluding the end of range would change the validated range when the valid_datetime is equal to valid_to, so gt is changed to gteq.

This change has little to no user impact, it's just a refactoring.

@wata727 wata727 force-pushed the exclude_end_in_uniqueness branch from cd29389 to 495a120 Compare December 24, 2024 12:53
@wata727 wata727 marked this pull request as ready for review January 7, 2025 11:08
@auto-assign auto-assign bot requested review from mkmn and yono January 7, 2025 11:08
@wata727 wata727 requested review from krororo and kumaie-shr and removed request for yono and mkmn January 7, 2025 11:08
Copy link

@kumaie-shr kumaie-shr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

Copy link
Collaborator

@krororo krororo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@wata727 wata727 merged commit 7146f90 into kufu:master Jan 9, 2025
10 checks passed
@wata727 wata727 deleted the exclude_end_in_uniqueness branch January 9, 2025 08:48
@wata727 wata727 mentioned this pull request Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants