From 21342d4bff94440b7ae58d381719a2a5d5e9b00b Mon Sep 17 00:00:00 2001 From: krororo Date: Sat, 17 Aug 2024 18:42:50 +0900 Subject: [PATCH] Support GlobalID --- activerecord-bitemporal.gemspec | 1 + lib/activerecord-bitemporal.rb | 2 + lib/activerecord-bitemporal/global_id.rb | 23 ++++++ .../activerecord-bitemporal/global_id_spec.rb | 75 +++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 lib/activerecord-bitemporal/global_id.rb create mode 100644 spec/activerecord-bitemporal/global_id_spec.rb diff --git a/activerecord-bitemporal.gemspec b/activerecord-bitemporal.gemspec index 65e2454..382d773 100644 --- a/activerecord-bitemporal.gemspec +++ b/activerecord-bitemporal.gemspec @@ -26,6 +26,7 @@ Gem::Specification.new do |spec| spec.add_dependency "activerecord", ">= 6.1" spec.add_development_dependency "bundler" + spec.add_development_dependency "globalid" spec.add_development_dependency "rake", "~> 13.0" spec.add_development_dependency "rspec", "~> 3.0" spec.add_development_dependency "pg" diff --git a/lib/activerecord-bitemporal.rb b/lib/activerecord-bitemporal.rb index a13e657..2a0a024 100644 --- a/lib/activerecord-bitemporal.rb +++ b/lib/activerecord-bitemporal.rb @@ -9,6 +9,7 @@ require "activerecord-bitemporal/version" require "activerecord-bitemporal/visualizer" require "activerecord-bitemporal/callbacks" +require "activerecord-bitemporal/global_id" module ActiveRecord::Bitemporal DEFAULT_VALID_FROM = Time.utc(1900, 12, 31).in_time_zone.freeze @@ -130,6 +131,7 @@ def bitemporalize( include InstanceMethods include ActiveRecord::Bitemporal::Scope include ActiveRecord::Bitemporal::Callbacks + prepend ActiveRecord::Bitemporal::GlobalID if defined?(GlobalID) if enable_merge_with_except_bitemporal_default_scope relation_delegate_class(ActiveRecord::Relation).prepend ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope diff --git a/lib/activerecord-bitemporal/global_id.rb b/lib/activerecord-bitemporal/global_id.rb new file mode 100644 index 0000000..5bea78e --- /dev/null +++ b/lib/activerecord-bitemporal/global_id.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +begin + require "globalid" +rescue LoadError + return +end + +module ActiveRecord + module Bitemporal + module GlobalID + include ::GlobalID::Identification + + def to_global_id(options = {}) + super(options.merge(app: "bitemporal")) + end + alias to_gid to_global_id + end + end +end + +# BiTemporal Data Model requires default scope, so `UnscopedLocator` cannot be used. +GlobalID::Locator.use "bitemporal", GlobalID::Locator::BaseLocator.new diff --git a/spec/activerecord-bitemporal/global_id_spec.rb b/spec/activerecord-bitemporal/global_id_spec.rb new file mode 100644 index 0000000..75e2a4b --- /dev/null +++ b/spec/activerecord-bitemporal/global_id_spec.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +require "spec_helper" + +GlobalID.app = "test-app" + +RSpec.describe "GlobalID" do + describe "#to_globalid" do + context "when BTDM" do + let(:company) { Company.create!(name: "Company1").tap { _1.update!(name: "Company2") } } + + it "app name is bitemporal" do + expect(company.to_global_id).to eq GlobalID.new("gid://bitemporal/Company/#{company.bitemporal_id}") + end + end + + context "when non BTDM" do + let(:non_btdm_class) do + Class.new(CompanyWithoutBitemporal) do + include GlobalID::Identification + + def self.name + "CompanyWithoutBitemporalGID" + end + end + end + let(:company) { non_btdm_class.create!(name: "Company1") } + + it "app name is default" do + expect(company.to_global_id).to eq GlobalID.new("gid://test-app/CompanyWithoutBitemporalGID/#{company.id}") + end + end + end + + describe "#to_gid" do + context "when BTDM" do + let(:company) { Company.create!(name: "Company1").tap { _1.update!(name: "Company2") } } + + it "app name is bitemporal" do + expect(company.to_gid).to eq GlobalID.new("gid://bitemporal/Company/#{company.bitemporal_id}") + end + end + + context "when non BTDM" do + let(:non_btdm_class) do + Class.new(CompanyWithoutBitemporal) do + include GlobalID::Identification + + def self.name + "CompanyWithoutBitemporalGID" + end + end + end + let(:company) { non_btdm_class.create!(name: "Company1") } + + it "app name is default" do + expect(company.to_gid).to eq GlobalID.new("gid://test-app/CompanyWithoutBitemporalGID/#{company.id}") + end + end + end + + describe "GlobalID::Locator.locate" do + let(:company) do + Company.create!(name: "Company1").tap do |m| + m.update!(name: "Company2") + m.update!(name: "Company3") + end + end + let(:gid) { company.to_global_id } + + it "can find current record" do + expect(GlobalID::Locator.locate(gid).name).to eq "Company3" + end + end +end