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 +4 -4
- data/.rubocop.yml +1 -1
- data/.tool-versions +1 -1
- data/CHANGELOG.md +4 -2
- data/README.md +3 -3
- data/lib/generators/hoardable/functions/hoardable_prevent_update_id.sql +8 -0
- data/lib/generators/hoardable/functions/hoardable_source_set_id.sql +18 -0
- data/lib/generators/hoardable/functions/hoardable_version_prevent_update.sql +6 -0
- data/lib/generators/hoardable/install_generator.rb +16 -2
- data/lib/generators/hoardable/migration_generator.rb +19 -1
- data/lib/generators/hoardable/templates/install.rb.erb +28 -59
- data/lib/generators/hoardable/templates/migration.rb.erb +7 -26
- data/lib/generators/hoardable/triggers/prevent_update_hoardable_id.sql +3 -0
- data/lib/generators/hoardable/triggers/set_hoardable_id.sql +3 -0
- data/lib/generators/hoardable/triggers/versions_prevent_update.sql +3 -0
- data/lib/hoardable/version.rb +1 -1
- metadata +30 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 83017b15a9b37931d02d7f5d8b7b8d3e81cab4b4cc4691f522430ae2c9be77f8
         | 
| 4 | 
            +
              data.tar.gz: 1774bb8cfe7628bbc2bdd8293928dac45dce20c4724aa5c4bc435a4c59a40f0d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: d0b7d0024a9b8eee5982ab92af174a9a7a134445108c1c3d97945c5ad967f234743fe047f0c42726366d38b7facacc44bac530a5de9a5369de0a9e7bc27342f9
         | 
| 7 | 
            +
              data.tar.gz: fb4d0de48b7d798e70c948aea4ae8adb90eaa2836c4ca2d76e952e5c02d53951205f2628bc3e620cb1824f6ac49fcc692dc19130f907c932e0ed3b78fee217e8
         | 
    
        data/.rubocop.yml
    CHANGED
    
    
    
        data/.tool-versions
    CHANGED
    
    | @@ -1,2 +1,2 @@ | |
| 1 | 
            -
            ruby 3.1 | 
| 1 | 
            +
            ruby 3.2.1
         | 
| 2 2 | 
             
            postgres 14.4
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # Hoardable 
         | 
| 2 2 |  | 
| 3 | 
            -
            Hoardable is an ActiveRecord extension for Ruby 2. | 
| 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  | 
| 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,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;$$;
         | 
| @@ -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  | 
| 30 | 
            -
                   | 
| 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 | 
| 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  | 
| 5 | 
            -
                 | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 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 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 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
         | 
    
        data/lib/hoardable/version.rb
    CHANGED
    
    
    
        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. | 
| 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:  | 
| 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. | 
| 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. | 
| 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
         |