hoardable 0.16.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c41a6c69f62f7e2a99fefe00229a7244f5cd0dcb9ed3b0d243db9adf9cabd98
4
- data.tar.gz: 30dc9d7a551c29331a7736f7b825c0b5f9db83bf5c5cd537d5d2910908f683ff
3
+ metadata.gz: 888659d9c6655e69c72fd8cf5b10b3697d5a81f432a44c8fa39984a05f4b23d9
4
+ data.tar.gz: ba850c1bf2363dd965a6e7780435d4feaf2ad417f2712f5f4635398ad5e9913d
5
5
  SHA512:
6
- metadata.gz: ad46ae05e3241052089aaf432016b906f648051fae6405e2ce4a90c7f247942a09a011d2fc35e6558695814949ef37a0398d36baaa71500f2c31d33436a7eac7
7
- data.tar.gz: b3307392cdff1b14a37192cd1a004099c5d99d7dd0ce3d0f8fe230c1dac4b59697c4708f5859cb7b2b831f45f1a3a6489cdce2eaf464fef2d9e135bd902e4f26
6
+ metadata.gz: 851d039e113df11834b18bb69edf786ba1d91598e408a45fab6ae7bb65efbc37264e4b803b8c8335f6839784f964f20d29c4c94b02aa6b994a21f3fd346ec162
7
+ data.tar.gz: 022a7ada38d996f8116a7ab8ed3d671e29055a8c75cc4155789ea3be135d87f24625ab67311c22f3b89b172320a973cbf203586407c6788750443bec90b461be
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.17.0
2
+
3
+ - Much improved performance of setting `hoardable_id` for versions.
4
+
1
5
  ## 0.16.0
2
6
 
3
7
  - Rails 8 support introduced
data/README.md CHANGED
@@ -235,6 +235,21 @@ version.changes # => { "title"=> ["Title", "New Title"] }
235
235
  version.hoardable_operation # => "update"
236
236
  ```
237
237
 
238
+ ### Overriding the temporal range
239
+
240
+ When calculating the temporal range for a given version, the default upper bound is `Time.now.utc`.
241
+
242
+ You can, however, use the `Hoardable.travel_to` class method to specify a custom upper bound for the time range. This allows
243
+ you to specify the datetime that a particular change should be recorded at by passing a block:
244
+
245
+ ```ruby
246
+ Hoardable.travel_to(2.weeks.ago) do
247
+ post.destroy!
248
+ end
249
+ ```
250
+
251
+ Note: If the provided datetime pre-dates the calculated lower bound then an `InvalidTemporalUpperBoundError` will be raised.
252
+
238
253
  ### Model Callbacks
239
254
 
240
255
  Sometimes you might want to do something with a version after it gets inserted to the database. You
@@ -0,0 +1,7 @@
1
+ CREATE OR REPLACE FUNCTION <%= function_name %>() RETURNS trigger
2
+ LANGUAGE plpgsql AS
3
+ $$
4
+ BEGIN
5
+ NEW.hoardable_id = NEW.<%= primary_key %>;
6
+ RETURN NEW;
7
+ END;$$;
@@ -25,7 +25,7 @@ module Hoardable
25
25
 
26
26
  def create_functions
27
27
  Dir
28
- .glob(File.join(__dir__, "functions", "*.sql"))
28
+ .glob(File.join(__dir__, "install_functions", "*.sql"))
29
29
  .each do |file_path|
30
30
  file_name = file_path.match(%r{([^/]+)\.sql})[1]
31
31
  template file_path, "db/functions/#{file_name}_v01.sql"
@@ -36,7 +36,15 @@ module Hoardable
36
36
  end
37
37
  end
38
38
 
39
+ def create_function
40
+ template("../functions/set_hoardable_id.sql", "db/functions/#{function_name}_v01.sql")
41
+ end
42
+
39
43
  no_tasks do
44
+ def function_name
45
+ "hoardable_set_hoardable_id_from_#{primary_key}"
46
+ end
47
+
40
48
  def table_name
41
49
  class_name.singularize.constantize.table_name
42
50
  rescue StandardError
@@ -4,7 +4,6 @@ class InstallHoardable < ActiveRecord::Migration[<%= ActiveRecord::Migration.cur
4
4
  def change
5
5
  <% if postgres_version < 13 %>enable_extension :pgcrypto
6
6
  <% end %>create_function :hoardable_prevent_update_id
7
- create_function :hoardable_source_set_id
8
7
  create_function :hoardable_version_prevent_update
9
8
  create_enum :hoardable_operation, %w[update delete insert]
10
9
  end
@@ -6,7 +6,7 @@ class Create<%= class_name.singularize.delete(':') %>Versions < ActiveRecord::Mi
6
6
  add_index :<%= table_name %>, :hoardable_id
7
7
  create_table(
8
8
  :<%= singularized_table_name %>_versions,
9
- id: false,
9
+ id: false,
10
10
  options: 'INHERITS (<%= table_name %>)',
11
11
  ) do |t|
12
12
  t.jsonb :_data
@@ -25,6 +25,7 @@ class Create<%= class_name.singularize.delete(':') %>Versions < ActiveRecord::Mi
25
25
  :<%= singularized_table_name %>_versions_prevent_update,
26
26
  on: :<%= singularized_table_name %>_versions
27
27
  )
28
+ create_function :<%= function_name %>
28
29
  create_trigger :<%= table_name %>_set_hoardable_id, on: :<%= table_name %>
29
30
  create_trigger :<%= table_name %>_prevent_update_hoardable_id, on: :<%= table_name %>
30
31
  change_column_null :<%= table_name %>, :hoardable_id, false
@@ -1,3 +1,3 @@
1
1
  CREATE TRIGGER <%= table_name %>_set_hoardable_id
2
2
  BEFORE INSERT ON <%= table_name %> FOR EACH ROW
3
- EXECUTE PROCEDURE hoardable_source_set_id();
3
+ EXECUTE PROCEDURE <%= function_name %>();
@@ -93,7 +93,14 @@ module Hoardable
93
93
  end
94
94
 
95
95
  def initialize_temporal_range
96
- ((previous_temporal_tsrange_end || hoardable_source_epoch)..Time.now.utc)
96
+ upper_bound = Hoardable.instance_variable_get("@travel_to") || Time.now.utc
97
+ lower_bound = (previous_temporal_tsrange_end || hoardable_source_epoch)
98
+
99
+ if upper_bound < lower_bound
100
+ raise InvalidTemporalUpperBoundError.new(upper_bound, lower_bound)
101
+ end
102
+
103
+ (lower_bound..upper_bound)
97
104
  end
98
105
 
99
106
  def initialize_hoardable_data
@@ -81,6 +81,16 @@ module Hoardable
81
81
  @at = nil
82
82
  end
83
83
 
84
+ # Allows calling code to set the upper bound for the temporal range for recorded audits.
85
+ #
86
+ # @param datetime [DateTime] the datetime to temporally record versions at
87
+ def travel_to(datetime)
88
+ @travel_to = datetime
89
+ yield
90
+ ensure
91
+ @travel_to = nil
92
+ end
93
+
84
94
  # @!visibility private
85
95
  def logger
86
96
  @logger ||= ActiveSupport::TaggedLogging.new(Logger.new($stdout))
@@ -101,7 +111,7 @@ module Hoardable
101
111
  initializer "hoardable.schema_statements" do
102
112
  ActiveSupport.on_load(:active_record_postgresqladapter) do
103
113
  # We need to control the table dumping order of tables, so revert these to just +super+
104
- Fx::SchemaDumper::Trigger.module_eval("def tables(streams); super; end")
114
+ Fx::SchemaDumper.module_eval("def tables(streams); super; end")
105
115
 
106
116
  ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaDumper.prepend(SchemaDumper)
107
117
  ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements.prepend(SchemaStatements)
@@ -24,4 +24,14 @@ module Hoardable
24
24
  LOG
25
25
  end
26
26
  end
27
+
28
+ # An error to be raised when the provided temporal upper bound is before the calcualated lower bound.
29
+ class InvalidTemporalUpperBoundError < Error
30
+ def initialize(upper, lower)
31
+ super(<<~LOG)
32
+ 'The supplied value to `Hoardable.travel_to` (#{upper}) is before the calculated lower bound (#{lower}).
33
+ You must provide a datetime > the lower bound.
34
+ LOG
35
+ end
36
+ end
27
37
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hoardable
4
- VERSION = "0.16.0"
4
+ VERSION = "0.17.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoardable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - justin talbott
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-11 00:00:00.000000000 Z
11
+ date: 2024-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0.8'
61
+ version: '0.9'
62
62
  - - "<"
63
63
  - !ruby/object:Gem::Version
64
64
  version: '1'
@@ -68,7 +68,7 @@ dependencies:
68
68
  requirements:
69
69
  - - ">="
70
70
  - !ruby/object:Gem::Version
71
- version: '0.8'
71
+ version: '0.9'
72
72
  - - "<"
73
73
  - !ruby/object:Gem::Version
74
74
  version: '1'
@@ -106,9 +106,9 @@ files:
106
106
  - LICENSE.txt
107
107
  - README.md
108
108
  - Rakefile
109
- - lib/generators/hoardable/functions/hoardable_prevent_update_id.sql
110
- - lib/generators/hoardable/functions/hoardable_source_set_id.sql
111
- - lib/generators/hoardable/functions/hoardable_version_prevent_update.sql
109
+ - lib/generators/hoardable/functions/set_hoardable_id.sql
110
+ - lib/generators/hoardable/install_functions/hoardable_prevent_update_id.sql
111
+ - lib/generators/hoardable/install_functions/hoardable_version_prevent_update.sql
112
112
  - lib/generators/hoardable/install_generator.rb
113
113
  - lib/generators/hoardable/migration_generator.rb
114
114
  - lib/generators/hoardable/templates/install.rb.erb
@@ -1,18 +0,0 @@
1
- CREATE OR REPLACE FUNCTION hoardable_source_set_id() RETURNS trigger
2
- LANGUAGE plpgsql AS
3
- $$
4
- DECLARE
5
- _pk information_schema.constraint_column_usage.column_name%TYPE;
6
- _id _pk%TYPE;
7
- BEGIN
8
- SELECT c.column_name
9
- FROM information_schema.table_constraints t
10
- JOIN information_schema.constraint_column_usage c
11
- ON c.constraint_name = t.constraint_name
12
- WHERE c.table_name = TG_TABLE_NAME AND t.constraint_type = 'PRIMARY KEY'
13
- LIMIT 1
14
- INTO _pk;
15
- EXECUTE format('SELECT $1.%I', _pk) INTO _id USING NEW;
16
- NEW.hoardable_id = _id;
17
- RETURN NEW;
18
- END;$$;