activerecord-bitemporal 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b36848b2facc997f9179abd32f96d7fde53cd9464f9009fa25a1ca5f13f57890
4
- data.tar.gz: 8498da159a6e051841ce253b7051f0722b0cb33d2358fc13a1b3f5c0664cf1f7
3
+ metadata.gz: 7676d93276c1c24acbb001b135c344b94d3b0b8084d2ef17423c238b5e06bfaf
4
+ data.tar.gz: f07cc0d7a716c99d3d85f352588309351b3ed408e6ddec5ad153096dd2310786
5
5
  SHA512:
6
- metadata.gz: bd8c531ad27a3ba0693d3923a00f62abb4b730251e235d0f3a78b449f2fdc7336052a4e5c0115748330e95a6f75eff2f20dcfc71d3fa1360d3d7e4c98c2b38af
7
- data.tar.gz: fe72790fbcb1372f8127afe702cf2696f930c901aaa2b6243c913243b299a74917bca867d068e09039a6df001c942f7db81b0a3c64daa54a919bbdb4714de4ac
6
+ metadata.gz: 95b6ea9e934a5818d3fc3e0409faef14bde66aeafbd0a0a168a1649e3b88ed6a11a0e8174094f7527ae4ba47076449db17a17597b83587a8986815af458b6c19
7
+ data.tar.gz: ece5cc5e3a8846f6495b63b30eb35eb4648e95b712e582b72fa67dafd1cfe9af1384737a11cf272d06cf73ed9e9121a674a6e0ea90434edb77d1715603cf7ffe
data/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.1.0
4
+
5
+ ### Breaking Changed
6
+
7
+ ### Added
8
+
9
+ - [Support GlobalID integration #176](https://github.com/kufu/activerecord-bitemporal/pull/176)
10
+
11
+ ### Changed
12
+
13
+ - [Add explicit activesupport dependency #208](https://github.com/kufu/activerecord-bitemporal/pull/208)
14
+ - [Improve ValidDatetimeRangeError message with better grammar and context #207](https://github.com/kufu/activerecord-bitemporal/pull/207)
15
+ - [Delay execution of ActiveRecord::Base-related processing #189](https://github.com/kufu/activerecord-bitemporal/pull/189)
16
+
17
+ ### Deprecated
18
+
19
+ ### Removed
20
+
21
+ ### Fixed
22
+
23
+ ### Chores
24
+
25
+ - [Bump ruby/setup-ruby from 1.263.0 to 1.265.0 #223](https://github.com/kufu/activerecord-bitemporal/pull/223)
26
+ - [Update gemspec files to avoid using git #222](https://github.com/kufu/activerecord-bitemporal/pull/222)
27
+ - [Bump ruby/setup-ruby from 1.257.0 to 1.263.0 #221](https://github.com/kufu/activerecord-bitemporal/pull/221)
28
+ - [Add CodeSpell workflow for spell checking in pull requests #220](https://github.com/kufu/activerecord-bitemporal/pull/220)
29
+ - [Configure dependabot cooldown period to 3 days #219](https://github.com/kufu/activerecord-bitemporal/pull/219)
30
+ - [Bump ruby/setup-ruby from 1.255.0 to 1.257.0 #218](https://github.com/kufu/activerecord-bitemporal/pull/218)
31
+ - [Bump actions/checkout from 4.2.2 to 5.0.0 #215](https://github.com/kufu/activerecord-bitemporal/pull/215)
32
+ - [Bump ruby/setup-ruby from 1.254.0 to 1.255.0 #214](https://github.com/kufu/activerecord-bitemporal/pull/214)
33
+ - [Bump ruby/setup-ruby from 1.247.0 to 1.254.0 #213](https://github.com/kufu/activerecord-bitemporal/pull/213)
34
+ - [Bump ruby/setup-ruby from 1.247.0 to 1.253.0 #212](https://github.com/kufu/activerecord-bitemporal/pull/212)
35
+ - [Setup RuboCop #211](https://github.com/kufu/activerecord-bitemporal/pull/211)
36
+ - [Bump ruby/setup-ruby from 1.245.0 to 1.247.0 #210](https://github.com/kufu/activerecord-bitemporal/pull/210)
37
+ - [Using Trusted Publishing for RubyGems.org. #209](https://github.com/kufu/activerecord-bitemporal/pull/209)
38
+ - [Bump ruby/setup-ruby from 1.244.0 to 1.245.0 #206](https://github.com/kufu/activerecord-bitemporal/pull/206)
39
+
3
40
  ## 6.0.0
4
41
 
5
42
  ### Breaking Changed
@@ -26,7 +63,7 @@
26
63
 
27
64
  - [Add a note to the README that PostgreSQL is required to run the tests. #188](https://github.com/kufu/activerecord-bitemporal/pull/188)
28
65
  - [Remove specs for Rails 5.x #191](https://github.com/kufu/activerecord-bitemporal/pull/191)
29
- - [Update auto assgin member #193](https://github.com/kufu/activerecord-bitemporal/pull/193)
66
+ - [Update auto assign member #193](https://github.com/kufu/activerecord-bitemporal/pull/193)
30
67
  - [Pin GitHub Actions dependencies to specific commit hashes #194](https://github.com/kufu/activerecord-bitemporal/pull/194)
31
68
  - [Bump ruby/setup-ruby from 1.227.0 to 1.229.0 #195](https://github.com/kufu/activerecord-bitemporal/pull/195)
32
69
  - [Bump ruby/setup-ruby from 1.229.0 to 1.233.0 #197](https://github.com/kufu/activerecord-bitemporal/pull/197)
@@ -35,7 +72,7 @@
35
72
  - [Bump ruby/setup-ruby from 1.237.0 to 1.238.0 #201](https://github.com/kufu/activerecord-bitemporal/pull/201)
36
73
  - [Bump ruby/setup-ruby from 1.238.0 to 1.242.0 #202](https://github.com/kufu/activerecord-bitemporal/pull/202)
37
74
  - [Bump ruby/setup-ruby from 1.242.0 to 1.244.0 #203](https://github.com/kufu/activerecord-bitemporal/pull/203)
38
- - [Update auto assgin member #204](https://github.com/kufu/activerecord-bitemporal/pull/204)
75
+ - [Update auto assign member #204](https://github.com/kufu/activerecord-bitemporal/pull/204)
39
76
 
40
77
  ## 5.3.0
41
78
 
@@ -1,20 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "activerecord-bitemporal/bitemporal_checker"
3
4
  module ActiveRecord
4
5
  module Bitemporal
5
- module BitemporalChecker
6
- refine ::Class do
7
- def bi_temporal_model?
8
- include?(ActiveRecord::Bitemporal)
9
- end
10
- end
11
-
12
- refine ::ActiveRecord::Relation do
13
- def bi_temporal_model?
14
- klass.include?(ActiveRecord::Bitemporal)
15
- end
16
- end
17
- end
18
6
  using BitemporalChecker
19
7
 
20
8
  module Optionable
@@ -493,7 +481,10 @@ module ActiveRecord
493
481
  # 以前の履歴データは valid_to を詰めて保存
494
482
  before_instance[valid_to_key] = target_datetime
495
483
  if before_instance.valid_from_cannot_be_greater_equal_than_valid_to
496
- raise ValidDatetimeRangeError.new("#{valid_from_key} #{before_instance[valid_from_key]} can't be greater equal than #{valid_to_key} #{before_instance[valid_to_key]}")
484
+ message = "#{valid_from_key} #{before_instance[valid_from_key]} can't be " \
485
+ "greater than or equal to #{valid_to_key} #{before_instance[valid_to_key]} " \
486
+ "for #{self.class} with bitemporal_id=#{bitemporal_id}"
487
+ raise ValidDatetimeRangeError.new(message)
497
488
  end
498
489
  before_instance.transaction_from = current_time
499
490
 
@@ -501,7 +492,10 @@ module ActiveRecord
501
492
  after_instance[valid_from_key] = target_datetime
502
493
  after_instance[valid_to_key] = current_valid_record[valid_to_key]
503
494
  if after_instance.valid_from_cannot_be_greater_equal_than_valid_to
504
- raise ValidDatetimeRangeError.new("#{valid_from_key} #{after_instance[valid_from_key]} can't be greater equal than #{valid_to_key} #{after_instance[valid_to_key]}")
495
+ message = "#{valid_from_key} #{after_instance[valid_from_key]} can't be " \
496
+ "greater than or equal to #{valid_to_key} #{after_instance[valid_to_key]} " \
497
+ "for #{self.class} with bitemporal_id=#{bitemporal_id}"
498
+ raise ValidDatetimeRangeError.new(message)
505
499
  end
506
500
  after_instance.transaction_from = current_time
507
501
 
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Bitemporal
5
+ module BitemporalChecker
6
+ refine ::Class do
7
+ def bi_temporal_model?
8
+ include?(ActiveRecord::Bitemporal)
9
+ end
10
+ end
11
+
12
+ refine ::ActiveRecord::Relation do
13
+ def bi_temporal_model?
14
+ klass.include?(ActiveRecord::Bitemporal)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord::Bitemporal::Bitemporalize
4
+ using Module.new {
5
+ refine ::ActiveRecord::Base do
6
+ class << ::ActiveRecord::Base
7
+ def prepend_relation_delegate_class(mod)
8
+ relation_delegate_class(ActiveRecord::Relation).prepend mod
9
+ relation_delegate_class(ActiveRecord::AssociationRelation).prepend mod
10
+ end
11
+ end
12
+ end
13
+ }
14
+
15
+ module ClassMethods
16
+ include ActiveRecord::Bitemporal::Relation::Finder
17
+
18
+ def bitemporal_id_key
19
+ 'bitemporal_id'
20
+ end
21
+
22
+ # Override ActiveRecord::Core::ClassMethods#cached_find_by_statement
23
+ # `.find_by` not use caching
24
+ def cached_find_by_statement(key, &block)
25
+ ActiveRecord::StatementCache.create(connection, &block)
26
+ end
27
+
28
+ def inherited(klass)
29
+ super
30
+ klass.prepend_relation_delegate_class ActiveRecord::Bitemporal::Relation
31
+ klass.relation_delegate_class(ActiveRecord::Associations::CollectionProxy).prepend ActiveRecord::Bitemporal::CollectionProxy
32
+ if relation_delegate_class(ActiveRecord::Relation).ancestors.include? ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope
33
+ klass.relation_delegate_class(ActiveRecord::Relation).prepend ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope
34
+ end
35
+ end
36
+ end
37
+
38
+ module InstanceMethods
39
+ include ActiveRecord::Bitemporal::Persistence
40
+
41
+ def swap_id!(without_clear_changes_information: false)
42
+ @_swapped_id_previously_was = nil
43
+ @_swapped_id = self.id
44
+ self.id = self.send(bitemporal_id_key)
45
+ clear_attribute_changes([:id]) unless without_clear_changes_information
46
+ end
47
+
48
+ def swapped_id
49
+ @_swapped_id || self.id
50
+ end
51
+
52
+ def swapped_id_previously_was
53
+ @_swapped_id_previously_was
54
+ end
55
+
56
+ def bitemporal_id_key
57
+ self.class.bitemporal_id_key
58
+ end
59
+
60
+ def bitemporal_ignore_update_columns
61
+ []
62
+ end
63
+
64
+ def id_in_database
65
+ swapped_id.presence || super
66
+ end
67
+
68
+ def previously_force_updated?
69
+ @previously_force_updated
70
+ end
71
+
72
+ def valid_from_cannot_be_greater_equal_than_valid_to
73
+ if self[valid_from_key] && self[valid_to_key] && self[valid_from_key] >= self[valid_to_key]
74
+ errors.add(valid_from_key, "can't be greater equal than #{valid_to_key}")
75
+ end
76
+ end
77
+
78
+ def transaction_from_cannot_be_greater_equal_than_transaction_to
79
+ if transaction_from && transaction_to && transaction_from >= transaction_to
80
+ errors.add(:transaction_from, "can't be greater equal than transaction_to")
81
+ end
82
+ end
83
+ end
84
+
85
+ def bitemporalize(
86
+ enable_strict_by_validates_bitemporal_id: false,
87
+ enable_default_scope: true,
88
+ enable_merge_with_except_bitemporal_default_scope: false,
89
+ valid_from_key: :valid_from,
90
+ valid_to_key: :valid_to
91
+ )
92
+ return if ancestors.include? InstanceMethods
93
+
94
+ extend ClassMethods
95
+ include InstanceMethods
96
+ include ActiveRecord::Bitemporal
97
+ include ActiveRecord::Bitemporal::Scope
98
+ include ActiveRecord::Bitemporal::Callbacks
99
+ prepend ActiveRecord::Bitemporal::GlobalID if defined?(::GlobalID)
100
+
101
+ if enable_merge_with_except_bitemporal_default_scope
102
+ relation_delegate_class(ActiveRecord::Relation).prepend ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope
103
+ end
104
+
105
+ if enable_default_scope
106
+ default_scope {
107
+ bitemporal_default_scope
108
+ }
109
+ end
110
+
111
+ after_create do
112
+ # MEMO: #update_columns is not call #_update_row (and validations, callbacks)
113
+ update_columns(bitemporal_id_key => swapped_id) unless send(bitemporal_id_key)
114
+ swap_id!(without_clear_changes_information: true)
115
+ @previously_force_updated = false
116
+ end
117
+
118
+ after_find do
119
+ self.swap_id! if self.send(bitemporal_id_key).present?
120
+ @previously_force_updated = false
121
+ end
122
+
123
+ self.class_attribute :valid_from_key, :valid_to_key, instance_writer: false
124
+ self.valid_from_key = valid_from_key.to_s
125
+ self.valid_to_key = valid_to_key.to_s
126
+ attribute valid_from_key, default: ActiveRecord::Bitemporal::DEFAULT_VALID_FROM
127
+ attribute valid_to_key, default: ActiveRecord::Bitemporal::DEFAULT_VALID_TO
128
+ attribute :transaction_from, default: ActiveRecord::Bitemporal::DEFAULT_TRANSACTION_FROM
129
+ attribute :transaction_to, default: ActiveRecord::Bitemporal::DEFAULT_TRANSACTION_TO
130
+
131
+ # Callback hook to `validates :xxx, uniqueness: true`
132
+ const_set(:UniquenessValidator, Class.new(ActiveRecord::Validations::UniquenessValidator) {
133
+ prepend ActiveRecord::Bitemporal::Uniqueness
134
+ })
135
+
136
+ # validations
137
+ validates valid_from_key, presence: true
138
+ validates valid_to_key, presence: true
139
+ validates :transaction_from, presence: true
140
+ validates :transaction_to, presence: true
141
+ validate :valid_from_cannot_be_greater_equal_than_valid_to
142
+ validate :transaction_from_cannot_be_greater_equal_than_transaction_to
143
+
144
+ validates bitemporal_id_key, uniqueness: true, allow_nil: true, strict: enable_strict_by_validates_bitemporal_id
145
+
146
+ prepend_relation_delegate_class ActiveRecord::Bitemporal::Relation
147
+ relation_delegate_class(ActiveRecord::Associations::CollectionProxy).prepend ActiveRecord::Bitemporal::CollectionProxy
148
+ end
149
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "globalid"
5
+ rescue LoadError
6
+ # If GlobalID is not available, we skip the GlobalID integration.
7
+ return
8
+ end
9
+
10
+ module ActiveRecord
11
+ module Bitemporal
12
+ module GlobalID
13
+ include ::GlobalID::Identification
14
+
15
+ def to_global_id(options = {})
16
+ super(options.merge(app: "bitemporal"))
17
+ end
18
+ alias to_gid to_global_id
19
+
20
+ class BitemporalLocator < ::GlobalID::Locator::BaseLocator
21
+ private
22
+
23
+ # @override https://github.com/rails/globalid/blob/v1.2.1/lib/global_id/locator.rb#L203
24
+ def primary_key(model_class)
25
+ model_class.respond_to?(:bitemporal_id_key) ? model_class.bitemporal_id_key : :id
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ # BiTemporal Data Model requires default scope, so `UnscopedLocator` cannot be used.
33
+ GlobalID::Locator.use :bitemporal, ActiveRecord::Bitemporal::GlobalID::BitemporalLocator.new
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "activerecord-bitemporal/bitemporal_checker"
4
+
3
5
  module ActiveRecord::Bitemporal
4
6
  module NodeBitemporalInclude
5
7
  refine String do
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Bitemporal
5
- VERSION = "6.0.0"
5
+ VERSION = "6.1.0"
6
6
  end
7
7
  end
@@ -2,13 +2,12 @@
2
2
 
3
3
  require "active_record"
4
4
  require "active_support/core_ext/time/calculations"
5
- require "activerecord-bitemporal/bitemporal"
6
5
  require "activerecord-bitemporal/scope"
7
6
  require "activerecord-bitemporal/errors"
8
- require "activerecord-bitemporal/patches"
9
7
  require "activerecord-bitemporal/version"
10
8
  require "activerecord-bitemporal/visualizer"
11
9
  require "activerecord-bitemporal/callbacks"
10
+ require "activerecord-bitemporal/global_id"
12
11
 
13
12
  module ActiveRecord::Bitemporal
14
13
  DEFAULT_VALID_FROM = Time.utc(1900, 12, 31).in_time_zone.freeze
@@ -22,154 +21,11 @@ module ActiveRecord::Bitemporal
22
21
  end
23
22
  end
24
23
 
25
- module ActiveRecord::Bitemporal::Bitemporalize
26
- using Module.new {
27
- refine ::ActiveRecord::Base do
28
- class << ::ActiveRecord::Base
29
- def prepend_relation_delegate_class(mod)
30
- relation_delegate_class(ActiveRecord::Relation).prepend mod
31
- relation_delegate_class(ActiveRecord::AssociationRelation).prepend mod
32
- end
33
- end
34
- end
35
- }
36
-
37
- module ClassMethods
38
- include ActiveRecord::Bitemporal::Relation::Finder
39
-
40
- def bitemporal_id_key
41
- 'bitemporal_id'
42
- end
43
-
44
- # Override ActiveRecord::Core::ClassMethods#cached_find_by_statement
45
- # `.find_by` not use caching
46
- def cached_find_by_statement(key, &block)
47
- ActiveRecord::StatementCache.create(connection, &block)
48
- end
49
-
50
- def inherited(klass)
51
- super
52
- klass.prepend_relation_delegate_class ActiveRecord::Bitemporal::Relation
53
- klass.relation_delegate_class(ActiveRecord::Associations::CollectionProxy).prepend ActiveRecord::Bitemporal::CollectionProxy
54
- if relation_delegate_class(ActiveRecord::Relation).ancestors.include? ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope
55
- klass.relation_delegate_class(ActiveRecord::Relation).prepend ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope
56
- end
57
- end
58
- end
59
-
60
- module InstanceMethods
61
- include ActiveRecord::Bitemporal::Persistence
62
-
63
- def swap_id!(without_clear_changes_information: false)
64
- @_swapped_id_previously_was = nil
65
- @_swapped_id = self.id
66
- self.id = self.send(bitemporal_id_key)
67
- clear_attribute_changes([:id]) unless without_clear_changes_information
68
- end
69
-
70
- def swapped_id
71
- @_swapped_id || self.id
72
- end
73
-
74
- def swapped_id_previously_was
75
- @_swapped_id_previously_was
76
- end
77
-
78
- def bitemporal_id_key
79
- self.class.bitemporal_id_key
80
- end
81
-
82
- def bitemporal_ignore_update_columns
83
- []
84
- end
85
-
86
- def id_in_database
87
- swapped_id.presence || super
88
- end
89
-
90
- def previously_force_updated?
91
- @previously_force_updated
92
- end
93
-
94
- def valid_from_cannot_be_greater_equal_than_valid_to
95
- if self[valid_from_key] && self[valid_to_key] && self[valid_from_key] >= self[valid_to_key]
96
- errors.add(valid_from_key, "can't be greater equal than #{valid_to_key}")
97
- end
98
- end
99
-
100
- def transaction_from_cannot_be_greater_equal_than_transaction_to
101
- if transaction_from && transaction_to && transaction_from >= transaction_to
102
- errors.add(:transaction_from, "can't be greater equal than transaction_to")
103
- end
104
- end
105
- end
106
-
107
- def bitemporalize(
108
- enable_strict_by_validates_bitemporal_id: false,
109
- enable_default_scope: true,
110
- enable_merge_with_except_bitemporal_default_scope: false,
111
- valid_from_key: :valid_from,
112
- valid_to_key: :valid_to
113
- )
114
- return if ancestors.include? InstanceMethods
115
-
116
- extend ClassMethods
117
- include InstanceMethods
118
- include ActiveRecord::Bitemporal
119
- include ActiveRecord::Bitemporal::Scope
120
- include ActiveRecord::Bitemporal::Callbacks
121
-
122
- if enable_merge_with_except_bitemporal_default_scope
123
- relation_delegate_class(ActiveRecord::Relation).prepend ActiveRecord::Bitemporal::Relation::MergeWithExceptBitemporalDefaultScope
124
- end
125
-
126
- if enable_default_scope
127
- default_scope {
128
- bitemporal_default_scope
129
- }
130
- end
131
-
132
- after_create do
133
- # MEMO: #update_columns is not call #_update_row (and validations, callbacks)
134
- update_columns(bitemporal_id_key => swapped_id) unless send(bitemporal_id_key)
135
- swap_id!(without_clear_changes_information: true)
136
- @previously_force_updated = false
137
- end
138
-
139
- after_find do
140
- self.swap_id! if self.send(bitemporal_id_key).present?
141
- @previously_force_updated = false
142
- end
143
-
144
- self.class_attribute :valid_from_key, :valid_to_key, instance_writer: false
145
- self.valid_from_key = valid_from_key.to_s
146
- self.valid_to_key = valid_to_key.to_s
147
- attribute valid_from_key, default: ActiveRecord::Bitemporal::DEFAULT_VALID_FROM
148
- attribute valid_to_key, default: ActiveRecord::Bitemporal::DEFAULT_VALID_TO
149
- attribute :transaction_from, default: ActiveRecord::Bitemporal::DEFAULT_TRANSACTION_FROM
150
- attribute :transaction_to, default: ActiveRecord::Bitemporal::DEFAULT_TRANSACTION_TO
151
-
152
- # Callback hook to `validates :xxx, uniqueness: true`
153
- const_set(:UniquenessValidator, Class.new(ActiveRecord::Validations::UniquenessValidator) {
154
- prepend ActiveRecord::Bitemporal::Uniqueness
155
- })
156
-
157
- # validations
158
- validates valid_from_key, presence: true
159
- validates valid_to_key, presence: true
160
- validates :transaction_from, presence: true
161
- validates :transaction_to, presence: true
162
- validate :valid_from_cannot_be_greater_equal_than_valid_to
163
- validate :transaction_from_cannot_be_greater_equal_than_transaction_to
164
-
165
- validates bitemporal_id_key, uniqueness: true, allow_nil: true, strict: enable_strict_by_validates_bitemporal_id
166
-
167
- prepend_relation_delegate_class ActiveRecord::Bitemporal::Relation
168
- relation_delegate_class(ActiveRecord::Associations::CollectionProxy).prepend ActiveRecord::Bitemporal::CollectionProxy
169
- end
170
- end
171
-
172
24
  ActiveSupport.on_load(:active_record) do
25
+ require "activerecord-bitemporal/bitemporal"
26
+ require "activerecord-bitemporal/bitemporalize"
27
+ require "activerecord-bitemporal/patches"
28
+
173
29
  ActiveRecord::Base
174
30
  .extend ActiveRecord::Bitemporal::Bitemporalize
175
31
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-bitemporal
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SmartHR
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-06-02 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -24,6 +23,20 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '7.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: activesupport
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '7.0'
27
40
  - !ruby/object:Gem::Dependency
28
41
  name: bundler
29
42
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +51,20 @@ dependencies:
38
51
  - - ">="
39
52
  - !ruby/object:Gem::Version
40
53
  version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: globalid
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
41
68
  - !ruby/object:Gem::Dependency
42
69
  name: rake
43
70
  requirement: !ruby/object:Gem::Requirement
@@ -129,30 +156,16 @@ executables: []
129
156
  extensions: []
130
157
  extra_rdoc_files: []
131
158
  files:
132
- - ".github/auto_assign.yml"
133
- - ".github/dependabot.yml"
134
- - ".github/workflows/release.yml"
135
- - ".github/workflows/test.yml"
136
- - ".gitignore"
137
- - Appraisals
138
159
  - CHANGELOG.md
139
- - CODE_OF_CONDUCT.jp.md
140
- - CODE_OF_CONDUCT.md
141
- - Gemfile
142
160
  - LICENSE
143
161
  - README.md
144
- - Rakefile
145
- - activerecord-bitemporal.gemspec
146
- - bin/console
147
- - bin/setup
148
- - compose.yml
149
- - gemfiles/rails_7.0.gemfile
150
- - gemfiles/rails_7.1.gemfile
151
- - gemfiles/rails_7.2.gemfile
152
162
  - lib/activerecord-bitemporal.rb
153
163
  - lib/activerecord-bitemporal/bitemporal.rb
164
+ - lib/activerecord-bitemporal/bitemporal_checker.rb
165
+ - lib/activerecord-bitemporal/bitemporalize.rb
154
166
  - lib/activerecord-bitemporal/callbacks.rb
155
167
  - lib/activerecord-bitemporal/errors.rb
168
+ - lib/activerecord-bitemporal/global_id.rb
156
169
  - lib/activerecord-bitemporal/patches.rb
157
170
  - lib/activerecord-bitemporal/scope.rb
158
171
  - lib/activerecord-bitemporal/version.rb
@@ -161,7 +174,6 @@ homepage: https://github.com/kufu/activerecord-bitemporal
161
174
  licenses:
162
175
  - Apache 2.0
163
176
  metadata: {}
164
- post_install_message:
165
177
  rdoc_options: []
166
178
  require_paths:
167
179
  - lib
@@ -176,8 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
188
  - !ruby/object:Gem::Version
177
189
  version: '0'
178
190
  requirements: []
179
- rubygems_version: 3.3.27
180
- signing_key:
191
+ rubygems_version: 3.6.9
181
192
  specification_version: 4
182
193
  summary: BiTemporal Data Model for ActiveRecord
183
194
  test_files: []
@@ -1,21 +0,0 @@
1
- # Set to true to add reviewers to pull requests
2
- addReviewers: true
3
-
4
- # Set to true to add assignees to pull requests
5
- addAssignees: false
6
-
7
- # A list of reviewers to be added to pull requests (GitHub user name)
8
- reviewers:
9
- - krororo
10
- - lighty
11
- - mkmn
12
- - osyo-manga
13
- - yono
14
- - kumaie-shr
15
-
16
- # A list of keywords to be skipped the process that add reviewers if pull requests include it
17
- skipKeywords:
18
-
19
- # A number of reviewers added to the pull request
20
- # Set 0 to add all the reviewers (default: 0)
21
- numberOfReviewers: 2
@@ -1,6 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: "github-actions"
4
- directory: "/"
5
- schedule:
6
- interval: "weekly"
@@ -1,37 +0,0 @@
1
- name: Push to rubygems.org
2
-
3
- on:
4
- workflow_dispatch:
5
- inputs:
6
- rubygems-otp-code:
7
- description: RubyGems OTP code
8
- required: true
9
- type: string
10
- email:
11
- description: Your email
12
- required: true
13
- type: string
14
-
15
- jobs:
16
- release:
17
- runs-on: ubuntu-latest
18
- env:
19
- GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
20
- GEM_HOST_OTP_CODE: ${{ github.event.inputs.rubygems-otp-code }}
21
- steps:
22
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
23
- with:
24
- fetch-depth: 0
25
-
26
- - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
27
- with:
28
- ruby-version: '3.1'
29
- bundler-cache: true
30
-
31
- - name: config
32
- run: |
33
- git config --global user.email ${{ github.event.inputs.email }}
34
- git config --global user.name ${{ github.actor }}
35
-
36
- - name: release
37
- run: bundle exec rake release
@@ -1,49 +0,0 @@
1
- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2
-
3
- name: Test
4
-
5
- on:
6
- push:
7
- branches:
8
- - master
9
- pull_request:
10
-
11
- jobs:
12
- test:
13
- runs-on: ubuntu-latest
14
- strategy:
15
- fail-fast: false
16
- matrix:
17
- ruby-version:
18
- - '3.1'
19
- - '3.2'
20
- - '3.3'
21
- - '3.4'
22
- gemfile:
23
- - rails_7.0
24
- - rails_7.1
25
- - rails_7.2
26
- services:
27
- postgres:
28
- image: postgres:14
29
- env:
30
- POSTGRES_PASSWORD: postgres
31
- # Set health checks to wait until postgres has started
32
- options: >-
33
- --health-cmd pg_isready
34
- --health-interval 10s
35
- --health-timeout 5s
36
- --health-retries 5
37
- ports:
38
- - 5432:5432
39
- env:
40
- BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
41
- steps:
42
- - name: Checkout
43
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
44
- - name: Setup Ruby
45
- uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
46
- with:
47
- ruby-version: ${{ matrix.ruby-version }}
48
- bundler-cache: true
49
- - run: bundle exec rspec
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- .bundle/
2
- .rspec_status
3
- Gemfile.lock
4
- gemfiles/*.gemfile.lock
data/Appraisals DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- appraise "rails-7.0" do
4
- gem "rails", "~> 7.0.1"
5
-
6
- # for Ruby 3.4
7
- gem "base64"
8
- gem "bigdecimal"
9
- gem "mutex_m"
10
-
11
- # NOTE: concurrent-ruby gem no longer loads the logger gem since v1.3.5.
12
- # https://github.com/ruby-concurrency/concurrent-ruby/pull/1062
13
- # https://github.com/rails/rails/pull/54264
14
- gem "concurrent-ruby", "< 1.3.5"
15
- end
16
-
17
- appraise "rails-7.1" do
18
- gem "rails", "~> 7.1.0"
19
- end
20
-
21
- appraise "rails-7.2" do
22
- gem "rails", "~> 7.2.0"
23
- end
@@ -1,86 +0,0 @@
1
- # コントリビューター行動規範
2
-
3
- ## 私たちの約束
4
- メンバー、コントリビューター、およびリーダーとして、年齢、体の大きさ、目に見えるまたは目に見えない障害、民族性、性別、
5
- 性同一性、表現、経験のレベル、教育、社会経済的地位、国籍、人格、人種、宗教、または性的同一性と指向に関係なく、
6
- コミュニティへの参加をハラスメントのない体験にすることを誓います。
7
-
8
- 私たちは、オープンで親しみやすく、多様で包括的で健全なコミュニティに貢献する方法で行動し、交流することを誓います。
9
-
10
- ## 私たちの標準
11
-
12
- 前向きな環境を作り上げることに貢献する行動の例:
13
-
14
- * 他人への共感と優しさを示す
15
-
16
- * 異なる意見、視点、経験を尊重する
17
-
18
- * 建設的なフィードバックを与え、優雅に受け入れる
19
-
20
- * 私たちの過ちの影響を受けた人々に責任を受け入れ、謝罪し、そしてその経験から学ぶ
21
-
22
- * 個人としてだけでなく、コミュニティ全体にとっても最善であることに焦点を当てる
23
-
24
- 許容できない行動の例は次のとおりです。
25
-
26
- * 性的な言葉や画像の使用、および性的な注意またはその他あらゆる種類の問題行為
27
-
28
- * トローリング、侮辱的または中傷的なコメント、個人的または政治的攻撃
29
-
30
- * 公的またはプライベートの嫌がらせ
31
-
32
- * 明示的な許可なしに、住所や電子メールアドレスなど、他者の個人情報を公開する
33
-
34
- * 職業上不適切と合理的に考えられるその他の行為
35
-
36
- ## 執行責任
37
-
38
- コミュニティリーダーは、許容される行動の基準を明確にし、実施する責任があり、不適切、脅迫的、攻撃的、または有害と見なされる行動に応じて、適切で公正な是正措置を講じます。
39
-
40
- コミュニティリーダーは、コメント、コミット、コード、wikiの編集、問題、およびこの行動規範に沿っていないその他の貢献を削除、編集、または拒否する権利と責任を持ち、適切な場合はモデレーションの決定の理由を伝えます。
41
-
42
- ## 適用範囲
43
-
44
- この行動規範は、すべてのコミュニティスペース内で適用され、個人がパブリックスペースでコミュニティを公式に代表している場合にも適用されます。
45
- 私たちのコミュニティを代表する例には、公式の電子メールアドレスの使用、公式のソーシャルメディアアカウントを介した投稿、オンラインまたはオフラインのイベントでの指定代理人としての行動などがあります。
46
-
47
- ## 執行
48
-
49
- 虐待的、嫌がらせ、またはその他の許容できない行動の事例は、執行を担当するコミュニティリーダーに対して `oss@smarthr.co.jp` で報告される場合があります。
50
- すべての苦情は迅速かつ公正にレビューおよび調査されます。
51
-
52
- すべてのコミュニティリーダーは、問題の報告者のプライバシーとセキュリティを尊重する義務があります。
53
-
54
- ## 執行ガイドライン
55
-
56
- コミュニティリーダーは、この行動規範に違反していると見なした行動への帰結を判断する際に、これらのコミュニティガイドラインに従います。
57
-
58
- ### 1. 更生
59
-
60
- **コミュニティへの影響**: コミュニティで専門家にふさわしくない、または歓迎されないと思われる不適切な言葉の使用やその他の不適切な行動をすること。
61
-
62
- **帰結**: コミュニティリーダーからの非公開の書面による警告。違反の理由を明確にし、行動が不適切だった理由を説明します。 公の謝罪が要求される場合があります。
63
-
64
- ### 2. 警告
65
-
66
- **コミュニティへの影響**: 単一の出来事または一連の動作による違反。
67
-
68
- **帰結**: 持続的な行動の結果を伴う警告。 指定された期間、行動規範の実施者との一方的な対話を含め、関係者との対話はありません。 これには、コミュニティスペースやソーシャルメディアなどの外部チャネルでの相互作用の回避が含まれます。 これらの条件に違反すると、一時的または永続的に禁止される場合があります。
69
-
70
- ### 3. 一時的な禁止
71
- **コミュニティへの影響**: 持続的で不適切な行動を含む、コミュニティ標準の重大な違反。
72
-
73
- **帰結**: 指定された期間のコミュニティとのあらゆる種類の相互関係または公的なコミュニケーションの一時的な禁止。 この期間中、行動規範を実施する人々との一方的な対話を含め、関係する人々との公的または私的な対話は許可されません。
74
- これらの条件に違反すると、永久的に禁止される場合があります。
75
- ### 4. 永久的な禁止
76
- **コミュニティへの影響**: 連続的な不適切な行動、個人への嫌がらせ、または個人の集団に対する攻撃または名誉毀損を含む、コミュニティの標準への違反のパターンを示す。
77
-
78
- **帰結**: コミュニティ内でのあらゆる種類の公的な相互関係の永久的な禁止。
79
-
80
- ## 帰属
81
- この行動規範は、https://www.contributor-covenant.org/version/2/0/code_of_conduct.html で利用可能な [Contributor Covenant][homepage] バージョン2.0を基に作成されています。
82
-
83
- コミュニティへの影響ガイドラインは[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity)に適合しています。
84
-
85
- [homepage]: https://www.contributor-covenant.org
86
- この行動規範に関する一般的な質問への回答については、https://www.contributor-covenant.org/faq のFAQを参照してください。翻訳はhttps://www.contributor-covenant.org/translations で入手できます。
data/CODE_OF_CONDUCT.md DELETED
@@ -1,133 +0,0 @@
1
-
2
- # Contributor Covenant Code of Conduct
3
-
4
- ## Our Pledge
5
-
6
- We as members, contributors, and leaders pledge to make participation in our
7
- community a harassment-free experience for everyone, regardless of age, body
8
- size, visible or invisible disability, ethnicity, sex characteristics, gender
9
- identity and expression, level of experience, education, socio-economic status,
10
- nationality, personal appearance, race, religion, or sexual identity
11
- and orientation.
12
-
13
- We pledge to act and interact in ways that contribute to an open, welcoming,
14
- diverse, inclusive, and healthy community.
15
-
16
- ## Our Standards
17
-
18
- Examples of behavior that contributes to a positive environment for our
19
- community include:
20
-
21
- * Demonstrating empathy and kindness toward other people
22
- * Being respectful of differing opinions, viewpoints, and experiences
23
- * Giving and gracefully accepting constructive feedback
24
- * Accepting responsibility and apologizing to those affected by our mistakes,
25
- and learning from the experience
26
- * Focusing on what is best not just for us as individuals, but for the
27
- overall community
28
-
29
- Examples of unacceptable behavior include:
30
-
31
- * The use of sexualized language or imagery, and sexual attention or
32
- advances of any kind
33
- * Trolling, insulting or derogatory comments, and personal or political attacks
34
- * Public or private harassment
35
- * Publishing others' private information, such as a physical or email
36
- address, without their explicit permission
37
- * Other conduct which could reasonably be considered inappropriate in a
38
- professional setting
39
-
40
- ## Enforcement Responsibilities
41
-
42
- Community leaders are responsible for clarifying and enforcing our standards of
43
- acceptable behavior and will take appropriate and fair corrective action in
44
- response to any behavior that they deem inappropriate, threatening, offensive,
45
- or harmful.
46
-
47
- Community leaders have the right and responsibility to remove, edit, or reject
48
- comments, commits, code, wiki edits, issues, and other contributions that are
49
- not aligned to this Code of Conduct, and will communicate reasons for moderation
50
- decisions when appropriate.
51
-
52
- ## Scope
53
-
54
- This Code of Conduct applies within all community spaces, and also applies when
55
- an individual is officially representing the community in public spaces.
56
- Examples of representing our community include using an official e-mail address,
57
- posting via an official social media account, or acting as an appointed
58
- representative at an online or offline event.
59
-
60
- ## Enforcement
61
-
62
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
63
- reported to the community leaders responsible for enforcement at
64
- `oss@smarthr.co.jp`.
65
- All complaints will be reviewed and investigated promptly and fairly.
66
-
67
- All community leaders are obligated to respect the privacy and security of the
68
- reporter of any incident.
69
-
70
- ## Enforcement Guidelines
71
-
72
- Community leaders will follow these Community Impact Guidelines in determining
73
- the consequences for any action they deem in violation of this Code of Conduct:
74
-
75
- ### 1. Correction
76
-
77
- **Community Impact**: Use of inappropriate language or other behavior deemed
78
- unprofessional or unwelcome in the community.
79
-
80
- **Consequence**: A private, written warning from community leaders, providing
81
- clarity around the nature of the violation and an explanation of why the
82
- behavior was inappropriate. A public apology may be requested.
83
-
84
- ### 2. Warning
85
-
86
- **Community Impact**: A violation through a single incident or series
87
- of actions.
88
-
89
- **Consequence**: A warning with consequences for continued behavior. No
90
- interaction with the people involved, including unsolicited interaction with
91
- those enforcing the Code of Conduct, for a specified period of time. This
92
- includes avoiding interactions in community spaces as well as external channels
93
- like social media. Violating these terms may lead to a temporary or
94
- permanent ban.
95
-
96
- ### 3. Temporary Ban
97
-
98
- **Community Impact**: A serious violation of community standards, including
99
- sustained inappropriate behavior.
100
-
101
- **Consequence**: A temporary ban from any sort of interaction or public
102
- communication with the community for a specified period of time. No public or
103
- private interaction with the people involved, including unsolicited interaction
104
- with those enforcing the Code of Conduct, is allowed during this period.
105
- Violating these terms may lead to a permanent ban.
106
-
107
- ### 4. Permanent Ban
108
-
109
- **Community Impact**: Demonstrating a pattern of violation of community
110
- standards, including sustained inappropriate behavior, harassment of an
111
- individual, or aggression toward or disparagement of classes of individuals.
112
-
113
- **Consequence**: A permanent ban from any sort of public interaction within
114
- the community.
115
-
116
- ## Attribution
117
-
118
- This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119
- version 2.0, available at
120
- [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
121
-
122
- Community Impact Guidelines were inspired by
123
- [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124
-
125
- For answers to common questions about this code of conduct, see the FAQ at
126
- [https://www.contributor-covenant.org/faq][FAQ]. Translations are available
127
- at [https://www.contributor-covenant.org/translations][translations].
128
-
129
- [homepage]: https://www.contributor-covenant.org
130
- [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
131
- [Mozilla CoC]: https://github.com/mozilla/diversity
132
- [FAQ]: https://www.contributor-covenant.org/faq
133
- [translations]: https://www.contributor-covenant.org/translations
data/Gemfile DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source "https://rubygems.org"
4
-
5
- git_source(:github) {|repo_name| "https://github.com/kufu/activerecord-bitemporal" }
6
-
7
- gemspec
8
-
9
- gem 'appraisal'
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- task :default => :spec
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path("../lib", __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require "activerecord-bitemporal/version"
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = "activerecord-bitemporal"
9
- spec.version = ActiveRecord::Bitemporal::VERSION
10
- spec.authors = ["SmartHR"]
11
- spec.email = ["oss@smarthr.co.jp"]
12
-
13
- spec.summary = "BiTemporal Data Model for ActiveRecord"
14
- spec.description = %q{Enable ActiveRecord models to be handled as BiTemporal Data Model.}
15
- spec.homepage = "https://github.com/kufu/activerecord-bitemporal"
16
- spec.license = "Apache 2.0"
17
- spec.required_ruby_version = ">= 3.1"
18
-
19
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
- f.match(%r{^(test|spec|features)/})
21
- end
22
- spec.bindir = "exe"
23
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
- spec.require_paths = ["lib"]
25
-
26
- spec.add_dependency "activerecord", ">= 7.0"
27
-
28
- spec.add_development_dependency "bundler"
29
- spec.add_development_dependency "rake", "~> 13.0"
30
- spec.add_development_dependency "rspec", "~> 3.0"
31
- spec.add_development_dependency "pg"
32
- spec.add_development_dependency "pry"
33
- spec.add_development_dependency "pry-byebug"
34
- spec.add_development_dependency "timecop"
35
- end
data/bin/console DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "activerecord-bitemporal"
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require "irb"
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/compose.yml DELETED
@@ -1,10 +0,0 @@
1
- services:
2
- db:
3
- image: postgres:latest
4
- ports:
5
- - "5432:5432"
6
- environment:
7
- POSTGRES_USER: postgres
8
- POSTGRES_PASSWORD: postgres
9
- tmpfs:
10
- - /var/lib/postgresql/data
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "rails", "~> 7.0.1"
7
- gem "base64"
8
- gem "bigdecimal"
9
- gem "mutex_m"
10
- gem "concurrent-ruby", "< 1.3.5"
11
-
12
- gemspec path: "../"
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "rails", "~> 7.1.0"
7
-
8
- gemspec path: "../"
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "rails", "~> 7.2.0"
7
-
8
- gemspec path: "../"