hoardable 0.13.0 → 0.14.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: 28edc85fff69a3851a5d2c653368d732bd9e6fe8ad5544bfa7f81147c6007aab
4
- data.tar.gz: 2d7c3abc9eedaddf3180b9f368c90fa25addaffa6c54bc76bf82880b54e7fc72
3
+ metadata.gz: 83017b15a9b37931d02d7f5d8b7b8d3e81cab4b4cc4691f522430ae2c9be77f8
4
+ data.tar.gz: 1774bb8cfe7628bbc2bdd8293928dac45dce20c4724aa5c4bc435a4c59a40f0d
5
5
  SHA512:
6
- metadata.gz: 76dfd695ad62332f876aad4d25e8d1b220970bcd8f2d2eeb69a91e4a441300fc356984dc5ef25be9dd01e745a305448a7f55b439199ef475932910bde02e8f9d
7
- data.tar.gz: '081e30627e731ed8d9b4f42536d9e67926bb37348075efa10d2ee3f5ee3eb37476ba3b0ecf1c6ac6fb4dfa7fa700e4d02fd10c3c3f537ef7ba433e605c9d1039'
6
+ metadata.gz: d0b7d0024a9b8eee5982ab92af174a9a7a134445108c1c3d97945c5ad967f234743fe047f0c42726366d38b7facacc44bac530a5de9a5369de0a9e7bc27342f9
7
+ data.tar.gz: fb4d0de48b7d798e70c948aea4ae8adb90eaa2836c4ca2d76e952e5c02d53951205f2628bc3e620cb1824f6ac49fcc692dc19130f907c932e0ed3b78fee217e8
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.6
2
+ TargetRubyVersion: 2.7
3
3
  NewCops: enable
4
4
  SuggestExtensions: false
5
5
 
data/.tool-versions CHANGED
@@ -1,2 +1,2 @@
1
- ruby 3.1.2
1
+ ruby 3.2.1
2
2
  postgres 14.4
data/CHANGELOG.md CHANGED
@@ -1,4 +1,6 @@
1
- ## [Unreleased]
1
+ ## 0.14.0
2
2
 
3
- - Stability is coming.
3
+ - *Breaking Change* - Support for Ruby 2.6 is dropped
4
+ - Adjusts the migration and install generators to use the `fx` gem so that Rails 7+ can use `schema.rb`
5
+ instead of `structure.sql`
4
6
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hoardable ![gem version](https://img.shields.io/gem/v/hoardable?style=flat-square)
2
2
 
3
- Hoardable is an ActiveRecord extension for Ruby 2.6+, Rails 6.1+, and PostgreSQL that allows for versioning
3
+ Hoardable is an ActiveRecord extension for Ruby 2.7+, Rails 6.1+, and PostgreSQL that allows for versioning
4
4
  and soft-deletion of records through the use of _uni-temporal inherited tables_.
5
5
 
6
6
  [Temporal tables](https://en.wikipedia.org/wiki/Temporal_database) are a database design pattern where each
@@ -34,8 +34,8 @@ bin/rails g hoardable:install
34
34
  bin/rails db:migrate
35
35
  ```
36
36
 
37
- This will generate PostgreSQL functions, an initiailzer, and set `config.active_record.schema_format = :sql`
38
- in `application.rb`.
37
+ This will generate PostgreSQL functions, an enum and an initiailzer. It will also set
38
+ `config.active_record.schema_format = :sql` in `application.rb` if you are using Rails < 7.
39
39
 
40
40
  ### Model Installation
41
41
 
@@ -0,0 +1,8 @@
1
+ CREATE OR REPLACE FUNCTION hoardable_prevent_update_id() RETURNS trigger
2
+ LANGUAGE plpgsql AS
3
+ $$BEGIN
4
+ IF NEW.hoardable_id <> OLD.hoardable_id THEN
5
+ RAISE EXCEPTION 'hoardable id cannot be updated';
6
+ END IF;
7
+ RETURN NEW;
8
+ END;$$;
@@ -0,0 +1,18 @@
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;$$;
@@ -0,0 +1,6 @@
1
+ CREATE OR REPLACE FUNCTION hoardable_version_prevent_update() RETURNS trigger
2
+ LANGUAGE plpgsql AS
3
+ $$BEGIN
4
+ RAISE EXCEPTION 'updating a version is not allowed';
5
+ RETURN NEW;
6
+ END;$$;
@@ -8,6 +8,7 @@ module Hoardable
8
8
  class InstallGenerator < Rails::Generators::Base
9
9
  source_root File.expand_path('templates', __dir__)
10
10
  include Rails::Generators::Migration
11
+ delegate :supports_schema_enums?, to: :class
11
12
 
12
13
  def create_initializer_file
13
14
  create_file(
@@ -22,12 +23,25 @@ module Hoardable
22
23
  )
23
24
  end
24
25
 
26
+ def change_schema_format_to_sql
27
+ return if supports_schema_enums?
28
+
29
+ application 'config.active_record.schema_format = :sql'
30
+ end
31
+
25
32
  def create_migration_file
26
33
  migration_template 'install.rb.erb', 'db/migrate/install_hoardable.rb'
27
34
  end
28
35
 
29
- def change_schema_format_to_sql
30
- application 'config.active_record.schema_format = :sql'
36
+ def create_functions
37
+ Dir.glob(File.join(__dir__, 'functions', '*.sql')).each do |file_path|
38
+ file_name = file_path.match(%r{([^/]+)\.sql})[1]
39
+ template file_path, "db/functions/#{file_name}_v01.sql"
40
+ end
41
+ end
42
+
43
+ def self.supports_schema_enums?
44
+ ActiveRecord.version >= ::Gem::Version.new('7.0.0')
31
45
  end
32
46
 
33
47
  def self.next_migration_number(dir)
@@ -9,12 +9,30 @@ module Hoardable
9
9
  class MigrationGenerator < ActiveRecord::Generators::Base
10
10
  source_root File.expand_path('templates', __dir__)
11
11
  include Rails::Generators::Migration
12
- class_option :foreign_key_type, type: :string
12
+ class_option(
13
+ :foreign_key_type,
14
+ type: :string,
15
+ optional: true,
16
+ desc: 'explictly set / override the foreign key type of the versions table'
17
+ )
13
18
 
14
19
  def create_versions_table
15
20
  migration_template 'migration.rb.erb', "db/migrate/create_#{singularized_table_name}_versions.rb"
16
21
  end
17
22
 
23
+ def create_triggers
24
+ {
25
+ versions_prevent_update: singularized_table_name,
26
+ set_hoardable_id: table_name,
27
+ prevent_update_hoardable_id: table_name
28
+ }.each do |(trigger_name, trigger_table_name)|
29
+ template(
30
+ "../triggers/#{trigger_name}.sql",
31
+ "db/triggers/#{trigger_table_name}_#{trigger_name}_v01.sql"
32
+ )
33
+ end
34
+ end
35
+
18
36
  no_tasks do
19
37
  def foreign_key_type
20
38
  options[:foreign_key_type] ||
@@ -1,65 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class InstallHoardable < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
4
- def up
5
- execute(
6
- <<~SQL.squish
7
- DO $$
8
- BEGIN
9
- IF NOT EXISTS (
10
- SELECT 1 FROM pg_type t WHERE t.typname = 'hoardable_operation'
11
- ) THEN
12
- CREATE TYPE hoardable_operation AS ENUM ('update', 'delete', 'insert');
13
- END IF;
14
- END
15
- $$;
4
+ def change
5
+ create_function :hoardable_prevent_update_id
6
+ create_function :hoardable_source_set_id
7
+ create_function :hoardable_version_prevent_update
8
+ <% if supports_schema_enums? %>
9
+ create_enum :hoardable_operation, %w[update delete insert]
10
+ <% else %>
11
+ reversible do |dir|
12
+ dir.up do
13
+ execute(
14
+ <<~SQL.squish
15
+ DO $$
16
+ BEGIN
17
+ IF NOT EXISTS (
18
+ SELECT 1 FROM pg_type t WHERE t.typname = 'hoardable_operation'
19
+ ) THEN
20
+ CREATE TYPE hoardable_operation AS ENUM ('update', 'delete', 'insert');
21
+ END IF;
22
+ END
23
+ $$;
24
+ SQL
25
+ )
26
+ end
16
27
 
17
- CREATE OR REPLACE FUNCTION hoardable_source_set_id() RETURNS trigger
18
- LANGUAGE plpgsql AS
19
- $$
20
- DECLARE
21
- _pk information_schema.constraint_column_usage.column_name%TYPE;
22
- _id _pk%TYPE;
23
- BEGIN
24
- SELECT c.column_name
25
- FROM information_schema.table_constraints t
26
- JOIN information_schema.constraint_column_usage c
27
- ON c.constraint_name = t.constraint_name
28
- WHERE c.table_name = TG_TABLE_NAME AND t.constraint_type = 'PRIMARY KEY'
29
- LIMIT 1
30
- INTO _pk;
31
- EXECUTE format('SELECT $1.%I', _pk) INTO _id USING NEW;
32
- NEW.hoardable_id = _id;
33
- RETURN NEW;
34
- END;$$;
35
-
36
- CREATE OR REPLACE FUNCTION hoardable_prevent_update_id() RETURNS trigger
37
- LANGUAGE plpgsql AS
38
- $$BEGIN
39
- IF NEW.hoardable_id <> OLD.hoardable_id THEN
40
- RAISE EXCEPTION 'hoardable id cannot be updated';
41
- END IF;
42
- RETURN NEW;
43
- END;$$;
44
-
45
- CREATE OR REPLACE FUNCTION hoardable_version_prevent_update() RETURNS trigger
46
- LANGUAGE plpgsql AS
47
- $$BEGIN
48
- RAISE EXCEPTION 'updating a version is not allowed';
49
- RETURN NEW;
50
- END;$$;
51
- SQL
52
- )
53
- end
54
-
55
- def down
56
- execute(
57
- <<~SQL.squish
58
- DROP TYPE IF EXISTS hoardable_operation;
59
- DROP FUNCTION IF EXISTS hoardable_version_prevent_update();
60
- DROP FUNCTION IF EXISTS hoardable_source_set_id();
61
- DROP FUNCTION IF EXISTS hoardable_prevent_update_id();
62
- SQL
63
- )
28
+ dir.down do
29
+ execute('DROP TYPE IF EXISTS hoardable_operation;')
30
+ end
31
+ end
32
+ <% end %>
64
33
  end
65
34
  end
@@ -12,34 +12,15 @@ class Create<%= class_name.singularize.delete(':') %>Versions < ActiveRecord::Mi
12
12
  end
13
13
  reversible do |dir|
14
14
  dir.up do
15
- execute(
16
- <<~SQL
17
- UPDATE <%= table_name %> SET hoardable_id = <%= primary_key %>;
18
- CREATE TRIGGER <%= singularized_table_name %>_versions_prevent_update
19
- BEFORE UPDATE ON <%= singularized_table_name %>_versions FOR EACH ROW
20
- EXECUTE PROCEDURE hoardable_version_prevent_update();
21
- CREATE TRIGGER <%= table_name %>_set_hoardable_id
22
- BEFORE INSERT ON <%= table_name %> FOR EACH ROW
23
- EXECUTE PROCEDURE hoardable_source_set_id();
24
- CREATE TRIGGER <%= table_name %>_prevent_update_hoardable_id
25
- BEFORE UPDATE ON <%= table_name %> FOR EACH ROW
26
- EXECUTE PROCEDURE hoardable_prevent_update_id();
27
- SQL
28
- )
29
- end
30
- dir.down do
31
- execute(
32
- <<~SQL
33
- DROP TRIGGER <%= singularized_table_name %>_versions_prevent_update
34
- ON <%= singularized_table_name %>_versions;
35
- DROP TRIGGER <%= table_name %>_set_hoardable_id
36
- ON <%= table_name %>;
37
- DROP TRIGGER <%= table_name %>_prevent_update_hoardable_id
38
- ON <%= table_name %>;
39
- SQL
40
- )
15
+ execute('UPDATE <%= table_name %> SET hoardable_id = <%= primary_key %>;')
41
16
  end
42
17
  end
18
+ create_trigger(
19
+ :<%= singularized_table_name %>_versions_prevent_update,
20
+ on: :<%= singularized_table_name %>_versions
21
+ )
22
+ create_trigger :<%= table_name %>_set_hoardable_id, on: :<%= table_name %>
23
+ create_trigger :<%= table_name %>_prevent_update_hoardable_id, on: :<%= table_name %>
43
24
  change_column_null :<%= table_name %>, :hoardable_id, false
44
25
  add_index :<%= singularized_table_name %>_versions, :<%= primary_key %>, unique: true
45
26
  add_index :<%= singularized_table_name %>_versions, :hoardable_id
@@ -0,0 +1,3 @@
1
+ CREATE TRIGGER <%= table_name %>_prevent_update_hoardable_id
2
+ BEFORE UPDATE ON <%= table_name %> FOR EACH ROW
3
+ EXECUTE PROCEDURE hoardable_prevent_update_id();
@@ -0,0 +1,3 @@
1
+ CREATE TRIGGER <%= table_name %>_set_hoardable_id
2
+ BEFORE INSERT ON <%= table_name %> FOR EACH ROW
3
+ EXECUTE PROCEDURE hoardable_source_set_id();
@@ -0,0 +1,3 @@
1
+ CREATE TRIGGER <%= singularized_table_name %>_versions_prevent_update
2
+ BEFORE UPDATE ON <%= singularized_table_name %>_versions FOR EACH ROW
3
+ EXECUTE PROCEDURE hoardable_version_prevent_update();
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hoardable
4
- VERSION = '0.13.0'
4
+ VERSION = '0.14.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.13.0
4
+ version: 0.14.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: 2022-12-09 00:00:00.000000000 Z
11
+ date: 2023-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -70,6 +70,26 @@ dependencies:
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
72
  version: '8'
73
+ - !ruby/object:Gem::Dependency
74
+ name: fx
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0.8'
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: '1'
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0.8'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '1'
73
93
  - !ruby/object:Gem::Dependency
74
94
  name: pg
75
95
  requirement: !ruby/object:Gem::Requirement
@@ -104,10 +124,16 @@ files:
104
124
  - LICENSE.txt
105
125
  - README.md
106
126
  - Rakefile
127
+ - lib/generators/hoardable/functions/hoardable_prevent_update_id.sql
128
+ - lib/generators/hoardable/functions/hoardable_source_set_id.sql
129
+ - lib/generators/hoardable/functions/hoardable_version_prevent_update.sql
107
130
  - lib/generators/hoardable/install_generator.rb
108
131
  - lib/generators/hoardable/migration_generator.rb
109
132
  - lib/generators/hoardable/templates/install.rb.erb
110
133
  - lib/generators/hoardable/templates/migration.rb.erb
134
+ - lib/generators/hoardable/triggers/prevent_update_hoardable_id.sql
135
+ - lib/generators/hoardable/triggers/set_hoardable_id.sql
136
+ - lib/generators/hoardable/triggers/versions_prevent_update.sql
111
137
  - lib/hoardable.rb
112
138
  - lib/hoardable/associations.rb
113
139
  - lib/hoardable/belongs_to.rb
@@ -141,14 +167,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
167
  requirements:
142
168
  - - ">="
143
169
  - !ruby/object:Gem::Version
144
- version: 2.6.0
170
+ version: 2.7.0
145
171
  required_rubygems_version: !ruby/object:Gem::Requirement
146
172
  requirements:
147
173
  - - ">="
148
174
  - !ruby/object:Gem::Version
149
175
  version: '0'
150
176
  requirements: []
151
- rubygems_version: 3.3.7
177
+ rubygems_version: 3.4.6
152
178
  signing_key:
153
179
  specification_version: 4
154
180
  summary: An ActiveRecord extension for versioning and soft-deletion of records in