back to home

kufu / activerecord-bitemporal

BiTemporal Data Model for ActiveRecord

View on GitHub
220 stars
49 forks
4 issues

AI Architecture Analysis

This repository is indexed by RepoMind. By analyzing kufu/activerecord-bitemporal in our AI interface, you can instantly generate complete architecture diagrams, visualize control flows, and perform automated security audits across the entire codebase.

Our Agentic Context Augmented Generation (Agentic CAG) engine loads full source files into context on-demand, avoiding the fragmentation of traditional RAG systems. Ask questions about the architecture, dependencies, or specific features to see it in action.

Source files are only loaded when you start an analysis to optimize performance.

Embed this Badge

Showcase RepoMind's analysis directly in your repository's README.

[![Analyzed by RepoMind](https://img.shields.io/badge/Analyzed%20by-RepoMind-4F46E5?style=for-the-badge)](https://repomind.in/repo/kufu/activerecord-bitemporal)
Preview:Analyzed by RepoMind

Repository Overview (README excerpt)

Crawler view

ActiveRecord::Bitemporal ======================== Requirements • Ruby 3.1+ • Rails 7.1, 7.2, 8.0, or 8.1 • PostgreSQL Installation Add this line to your application's Gemfile: And then execute: $ bundle Or install it yourself as: $ gem install activerecord-bitemporal 概要 activerecord-bitemporal は Rails の ActiveRecord で Bitemporal Data Model を扱うためのライブラリになります。 activerecord-bitemporal では、モデルを生成すると 以下のようなレコードが生成されます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 9999-12-31 | そのモデルに対して更新を行うと 次のような履歴レコードが暗黙的に生成されます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 2019-01-15 | | 2 | 1 | 001 | Jane | 2019-01-10 | 2019-01-15 | 2019-01-15 | 9999-12-31 | | 3 | 1 | 001 | Tom | 2019-01-15 | 9999-12-31 | 2019-01-15 | 9999-12-31 | 更に更新すると 更新する度にどんどん履歴レコードが増えていきます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 2019-01-15 | | 2 | 1 | 001 | Jane | 2019-01-10 | 2019-01-15 | 2019-01-15 | 9999-12-31 | | 3 | 1 | 001 | Tom | 2019-01-15 | 9999-12-31 | 2019-01-15 | 2019-01-20 | | 4 | 1 | 001 | Tom | 2019-01-15 | 2019-01-20 | 2019-01-20 | 9999-12-31 | | 5 | 1 | 001 | Kevin | 2019-01-20 | 9999-12-31 | 2019-01-20 | 9999-12-31 | また、レコードを読み込む場合は暗黙的に『一番最新のレコード』を参照します。 任意の時間の履歴レコードを参照したい場合は で時間指定して取得する事が出来ます。 このように activerecord-bitemporal は、 • 保存時に履歴レコードを自動生成 • 等で任意の時間のレコードを取得する というような事を行うライブラリになります。 モデルを BiTemporal Data Model 化する 任意のモデルを BiTemporal Data Model(以下、BTDM)として扱う場合は、以下のカラムを DB に追加する必要があります。 それぞれのカラムは以下のような意味を持ちます。 | カラム名 | 型 | 値 | | --- | --- | --- | | | と同じ型 | BTDM が共通で持つ | | | | 有効時間の開始時刻 | | | | 有効時間の終了時刻 | | | | システム時間の開始時刻 | | | | システム時間の終了時刻 | また、モデルクラスでは を をする必要があります。 これで モデルを BTDM として扱うことが出来ます。 このドキュメントではこのモデルをサンプルとしてコードを書いていきます。 モデルインスタンスに対する操作について ここではモデルの生成・更新・削除といったインスタンスに対する操作に関して解説します。 生成 以下のように BTDM を生成した場合、 以下のようなレコードが生成されます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 9999-12-31 | この時に生成されるレコードのカラムには暗黙的に以下のような値が保存されます。 | カラム | 値 | | --- | --- | | | 自身の | | | 生成した時間 | | | 擬似的な 時間 | これは『 から までの期間で有効なデータ』という意味になります。 また、 や を指定すれば『任意の時間』の履歴データも生成も出来ます。 更新 等でモデルを更新すると『更新時間』を基準とした履歴レコードが暗黙的に生成されます。 上記の操作を行うと以下のようなレコードが生成されます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 2019-01-20 | | 2 | 1 | 001 | Jane | 2019-01-10 | 2019-01-20 | 2019-01-20 | 9999-12-31 | | 3 | 1 | 001 | Tom | 2019-01-20 | 9999-12-31 | 2019-01-20 | 9999-12-31 | 更新時には以下のような処理を行っており、結果的に新しいレコードが2つ生成されることになります。 また、この時に生成されるレコードは共通の を保持します。 • 更新対象のレコード( )のシステム時間の終了時刻を更新する • 更新を行った時間までのレコード( )を新しく生成する • 更新を行った時間からのレコード( )を新しく生成する activerecord-bitemporal ではレコードの内容を変更する際にレコードを直接変更するのではなくて『既存のレコードはシステム時間では参照しないような時刻』にして『変更後のレコードを新しく生成』していきます。 ただし、 で更新を行うと強制的にレコードが上書きされるので注意してください。 上記の場合は以下のようなレコードになります。 のレコードが直接変更されるので注意してください。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Tom | 2019-01-10 | 9999-12-31 | 2019-01-10 | 9999-12-31 | 履歴を生成せずに上書きして更新したいのであれば activerecord-bitemporal 側で用意している を利用する事が出来ます。 上記の場合は以下のレコードが生成されます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 2019-01-20 | | 2 | 1 | 001 | Tom | 2019-01-10 | 9999-12-31 | 2019-01-20 | 9999-12-31 | この場合は はシステムの終了時刻が更新され、新しい のレコードが生成されます。 更新時間を指定して更新 TODO: 削除 更新と同様にレコードのシステム時間の終了時刻を更新しつつ、新しいレコードが生成されます。 上記の場合では以下のようなレコードが生成されます。 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 2019-01-20 | | 2 | 1 | 001 | Jane | 2019-01-10 | 2019-01-20 | 2019-01-20 | 9999-12-31 | | 3 | 1 | 001 | Tom | 2019-01-20 | 9999-12-31 | 2019-01-20 | 2019-01-30 | | 4 | 1 | 001 | Tom | 2019-01-20 | 2019-01-30 | 2019-01-30 | 9999-12-31 | 削除も更新と同様に • 削除対象のレコード( )のシステム時間の終了時刻を更新する • 削除を行った時間までの履歴レコード( )を新しく生成する という風に『システム時間の終了時刻を更新してから新しいレコードを生成する』という処理を行っています。 ユニーク制約 BTDM では『履歴の時間が被っている場合』にユニーク制約のバリデーションを行います。 また、 BTDM の もユニーク制約となっているので注意してください。 検索について BTDM のレコードの検索について解説します。 検索時にデフォルトで追加されるクエリ BTDM では DB からレコードを参照する場合、暗黙的に • 現在の時間を指定する時間指定クエリ • 論理削除を除くクエリ が追加された状態で SQL 文が構築されます。 これにより DB 上に複数の履歴レコードや論理削除されているレコードがあっても『現時点で有効な』レコードが参照されます。 このように『現在の時間で有効なレコード』のみが検索の対象となります。 また、これは ではなくて BTDM が独自にハックして暗黙的に追加する仕組みを実装しているので で取り除く事は出来ないので注意してください。 検索時にデフォルトクエリを取り除く 検索時にデフォルトクエリを取り除きたい場合、以下のスコープを使用します。 | スコープ | 動作 | | --- | --- | | | 時間指定を無視する | | | 論理削除されているレコードを含める | | | 全てのレコードを対象とする | 『任意のレコードの履歴一覧を取得する』ようなことを行う場合は を使用して全レコードを参照するようにします。 時間を指定して検索する 任意の時間を指定して検索を行いたい場合、 を利用する事が出来ます。 また、特定の で検索するのであれば も利用できます。 と について BTDM のインスタンスの は特殊で『レコードの 』ではなくて『 の値』が割り当てられています。 インスタンスの はレコードの読み込み時に自動的に設定されています。 これは で検索を行う際に の値が ではなくて のほうが実装上都合がいい、という由来になっています。 この影響により や 、 が返す結果が微妙に異なるので注意してください。 レコードの内容 | id | bitemporal_id | emp_code | name | valid_from | valid_to | transaction_from | transaction_to | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 001 | Jane | 2019-01-10 | 9999-12-31 | 2019-01-10 | 2019-01-15 | | 2 | 1 | 001 | Jane | 2019-01-10 | 2019-01-15 | 2019-01-15 | 9999…