logidze 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +16 -10
- data/lib/generators/logidze/install/functions/logidze_compact_history.sql +1 -1
- data/lib/generators/logidze/install/functions/logidze_filter_keys.sql +1 -1
- data/lib/generators/logidze/install/functions/logidze_logger.sql +1 -1
- data/lib/generators/logidze/install/functions/logidze_snapshot.sql +9 -1
- data/lib/generators/logidze/install/functions/logidze_version.sql +1 -1
- data/lib/generators/logidze/install/install_generator.rb +2 -17
- data/lib/generators/logidze/install/templates/hstore.rb.erb +1 -1
- data/lib/generators/logidze/install/templates/migration.rb.erb +1 -1
- data/lib/generators/logidze/install/templates/migration_fx.rb.erb +1 -1
- data/lib/generators/logidze/model/templates/migration.rb.erb +1 -1
- data/lib/logidze.rb +11 -1
- data/lib/logidze/engine.rb +9 -0
- data/lib/logidze/utils/check_pending.rb +57 -0
- data/lib/logidze/utils/function_definitions.rb +49 -0
- data/lib/logidze/utils/pending_migration_error.rb +25 -0
- data/lib/logidze/version.rb +1 -1
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6c441d5e6e60ef695eb354e4bfb5be9fa182bd8b70755d829aee6eb2781e401
|
4
|
+
data.tar.gz: d64374a0d6327f2f713fd7341c31de93472f32d045cb5c825c35874c756307d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3f453e410de263ed8b0704aece35e6274dfc19c9074a8f75450e84033318b149ae81c9e1f48cc9d515e523b95c98c14cbd3453a7c41db1690febfe8060f640d
|
7
|
+
data.tar.gz: dbf4a22b357889bc0d2aaeda52bffc8bc245cdc12d2cb34d0f7c9ccec7c0f60807ecc3cbd5272fee567420024309f8be05f6e1e8c9f45334ab3d2ad155a97a12
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## master (unreleased)
|
4
|
+
|
5
|
+
## 1.1.0 (2021-03-31)
|
6
|
+
|
7
|
+
- Add pending upgrade checks [Experimental]. ([@skryukov][])
|
8
|
+
|
9
|
+
Now Logidze can check for a pending upgrade. Use `Logidze.pending_upgrade = :warn` to be notified by warning, or `Logidze.pending_upgrade = :error` if you want Logidze to raise an error.
|
10
|
+
|
11
|
+
- [Fixes [#171](https://github.com/palkan/logidze/issues/171)] Stringify jsonb column values within snapshots. ([@skryukov][])
|
12
|
+
|
13
|
+
- [Fixes [#175](https://github.com/palkan/logidze/issues/175)] Set dynamic ActiveRecord version for migrations. ([@skryukov][])
|
14
|
+
|
15
|
+
- [Fixes [#184](https://github.com/palkan/logidze/issues/184)] Remove Rails meta-gem dependency ([@bf4][])
|
16
|
+
|
3
17
|
## 1.0.0 (2020-11-09)
|
4
18
|
|
5
19
|
- Add `--name` option to model generator to specify the migration name. ([@palkan][])
|
@@ -332,3 +346,4 @@ This is a quick fix for a more general problem (see [#59](https://github.com/pal
|
|
332
346
|
[@zocoi]: https://github.com/zocoi
|
333
347
|
[@duderman]: https://github.com/duderman
|
334
348
|
[@oleg-kiviljov]: https://github.com/oleg-kiviljov
|
349
|
+
[@skryukov]: https://github.com/skryukov
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[![Cult Of Martians](http://cultofmartians.com/assets/badges/badge.svg)](http://cultofmartians.com)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/logidze.svg)](https://rubygems.org/gems/logidze)
|
3
|
-
![Build](https://github.com/palkan/logidze/workflows/Build/badge.svg)
|
3
|
+
[![Build](https://github.com/palkan/logidze/workflows/Build/badge.svg)](https://github.com/palkan/logidze/actions)
|
4
4
|
[![Open Source Helpers](https://www.codetriage.com/palkan/logidze/badges/users.svg)](https://www.codetriage.com/palkan/logidze)
|
5
5
|
|
6
6
|
# Logidze
|
@@ -22,16 +22,16 @@ Other requirements:
|
|
22
22
|
|
23
23
|
## Links
|
24
24
|
|
25
|
+
- [Logidze 1.0: Active Record, Postgres, Rails, and time travel](https://evilmartians.com/chronicles/logidze-1-0-active-record-postgresql-rails-and-time-travel?utm_source=logidze)
|
25
26
|
- [Logidze: for all those tired of versioning data](https://evilmartians.com/chronicles/introducing-logidze?utm_source=logidze)
|
26
27
|
|
27
28
|
## Table of contents
|
28
29
|
|
29
|
-
- [Main concepts](#main-concepts)
|
30
30
|
- [Installation & Configuration](#installation)
|
31
31
|
- [Using with schema.rb](#using-with-schemarb)
|
32
32
|
- [Configuring models](#configuring-models)
|
33
33
|
- [Backfill data](#backfill-data)
|
34
|
-
- [Log size
|
34
|
+
- [Log size limits](#log-size-limits)
|
35
35
|
- [Tracking only selected columns](#tracking-only-selected-columns)
|
36
36
|
- [Logs timestamps](#logs-timestamps)
|
37
37
|
- [Usage](#usage)
|
@@ -439,7 +439,7 @@ See also the discussion: [#61](https://github.com/palkan/logidze/issues/61).
|
|
439
439
|
We try to make an upgrade process as simple as possible. For now, the only required action is to create and run a migration:
|
440
440
|
|
441
441
|
```sh
|
442
|
-
rails generate logidze:install --update
|
442
|
+
bundle exec rails generate logidze:install --update
|
443
443
|
```
|
444
444
|
|
445
445
|
This updates core `logdize_logger` DB function. No need to update tables or triggers.
|
@@ -449,31 +449,37 @@ This updates core `logdize_logger` DB function. No need to update tables or trig
|
|
449
449
|
If you want to update Logidze settings for the model, run migration with `--update` flag:
|
450
450
|
|
451
451
|
```sh
|
452
|
-
rails generate logidze:model Post --update --only=title,body,rating
|
452
|
+
bundle exec rails generate logidze:model Post --update --only=title,body,rating
|
453
453
|
```
|
454
454
|
|
455
455
|
You can also use the `--name` option to specify the migration name to avoid duplicate migration names:
|
456
456
|
|
457
457
|
```sh
|
458
|
-
$ rails generate logidze:model Post --update --only=title,body,rating --name add_only_filter_to_posts_log_data
|
458
|
+
$ bundle exec rails generate logidze:model Post --update --only=title,body,rating --name add_only_filter_to_posts_log_data
|
459
459
|
|
460
460
|
create db/migrate/20202309142344_add_only_filter_to_posts_log_data.rb
|
461
461
|
```
|
462
462
|
|
463
|
+
### Pending upgrade check [Experimental]
|
464
|
+
|
465
|
+
Logidze can check for a pending upgrade. Use `Logidze.pending_upgrade = :warn` to be notified by warning, or `Logidze.pending_upgrade = :error` if you want Logidze to raise an error.
|
466
|
+
|
463
467
|
### Upgrading from 0.x to 1.0 (edge)
|
464
468
|
|
465
469
|
#### Schema and migrations
|
466
470
|
|
467
|
-
Most SQL
|
471
|
+
Most SQL function definitions have changed without backward compatibility.
|
468
472
|
Perform the following steps to upgrade:
|
469
473
|
|
470
|
-
1. Re-install Logidze: `rails generate logidze:install --update`.
|
474
|
+
1. Re-install Logidze: `bundle exec rails generate logidze:install --update`.
|
475
|
+
|
476
|
+
1. Re-install Logidze triggers **for all models**: `bundle exec rails generate logidze:model <model> --update`.
|
471
477
|
|
472
|
-
|
478
|
+
**NOTE:** If you had previously specified whitelist/blacklist attributes, you will need to include the `--only`/`--except` [option](#tracking-only-selected-columns) as appropriate. You can easily copy these column lists from the previous logidze migration for the model.
|
473
479
|
|
474
480
|
1. Remove the `include Logidze::Migration` line from the old migration files (if any)—this module has been removed.
|
475
481
|
|
476
|
-
Rewrite
|
482
|
+
Rewrite legacy logidze migrations to not use the `#current_setting(name)` and `#current_setting_missing_supported?` methods, or copy them from the latest [0.x release](https://github.com/palkan/logidze/blob/0-stable/lib/logidze/migration.rb).
|
477
483
|
|
478
484
|
#### API changes
|
479
485
|
|
@@ -1,7 +1,8 @@
|
|
1
|
-
-- version: 1
|
2
1
|
CREATE OR REPLACE FUNCTION logidze_snapshot(item jsonb, ts_column text DEFAULT NULL, columns text[] DEFAULT NULL, include_columns boolean DEFAULT false) RETURNS jsonb AS $body$
|
2
|
+
-- version: 2
|
3
3
|
DECLARE
|
4
4
|
ts timestamp with time zone;
|
5
|
+
k text;
|
5
6
|
BEGIN
|
6
7
|
IF ts_column IS NULL THEN
|
7
8
|
ts := statement_timestamp();
|
@@ -13,6 +14,13 @@ CREATE OR REPLACE FUNCTION logidze_snapshot(item jsonb, ts_column text DEFAULT N
|
|
13
14
|
item := logidze_filter_keys(item, columns, include_columns);
|
14
15
|
END IF;
|
15
16
|
|
17
|
+
FOR k IN (SELECT key FROM jsonb_each(item))
|
18
|
+
LOOP
|
19
|
+
IF jsonb_typeof(item->k) = 'object' THEN
|
20
|
+
item := jsonb_set(item, ARRAY[k], to_jsonb(item->>k));
|
21
|
+
END IF;
|
22
|
+
END LOOP;
|
23
|
+
|
16
24
|
return json_build_object(
|
17
25
|
'v', 1,
|
18
26
|
'h', jsonb_build_array(
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "rails/generators"
|
4
4
|
require "rails/generators/active_record"
|
5
|
+
require "logidze/utils/function_definitions"
|
5
6
|
require_relative "../inject_sql"
|
6
7
|
require_relative "../fx_helper"
|
7
8
|
|
@@ -14,8 +15,6 @@ module Logidze
|
|
14
15
|
include InjectSql
|
15
16
|
include FxHelper
|
16
17
|
|
17
|
-
class FuncDef < Struct.new(:name, :version, :signature); end
|
18
|
-
|
19
18
|
source_root File.expand_path("templates", __dir__)
|
20
19
|
source_paths << File.expand_path("functions", __dir__)
|
21
20
|
|
@@ -80,21 +79,7 @@ module Logidze
|
|
80
79
|
end
|
81
80
|
|
82
81
|
def function_definitions
|
83
|
-
@function_definitions ||=
|
84
|
-
begin
|
85
|
-
Dir.glob(File.join(__dir__, "functions", "*.sql")).map do |path|
|
86
|
-
name = path.match(/([^\/]+)\.sql/)[1]
|
87
|
-
|
88
|
-
file = File.open(path)
|
89
|
-
header = file.readline
|
90
|
-
|
91
|
-
version = header.match(/version:\s+(\d+)/)[1].to_i
|
92
|
-
parameters = file.readline.match(/CREATE OR REPLACE FUNCTION\s+[\w_]+\((.*)\)/)[1]
|
93
|
-
signature = parameters.split(/\s*,\s*/).map { |param| param.split(/\s+/, 2).last.sub(/\s+DEFAULT .*$/, "") }.join(", ")
|
94
|
-
|
95
|
-
FuncDef.new(name, version, signature)
|
96
|
-
end
|
97
|
-
end
|
82
|
+
@function_definitions ||= Logidze::Utils::FunctionDefinitions.from_fs
|
98
83
|
end
|
99
84
|
end
|
100
85
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class <%= @migration_class_name %> < ActiveRecord::Migration[
|
1
|
+
class <%= @migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
2
2
|
def change
|
3
3
|
<%- unless update? || only_trigger? -%>
|
4
4
|
add_column :<%= table_name %>, :log_data, :jsonb
|
data/lib/logidze.rb
CHANGED
@@ -26,6 +26,8 @@ module Logidze
|
|
26
26
|
attr_accessor :ignore_log_data_by_default
|
27
27
|
# Whether #at should return self or nil when log_data is nil
|
28
28
|
attr_accessor :return_self_if_log_data_is_empty
|
29
|
+
# Determines what Logidze should do when upgrade is needed (:raise | :warn | :ignore)
|
30
|
+
attr_reader :on_pending_upgrade
|
29
31
|
|
30
32
|
# Temporary disable DB triggers.
|
31
33
|
#
|
@@ -35,7 +37,7 @@ module Logidze
|
|
35
37
|
with_logidze_setting("logidze.disabled", "on") { yield }
|
36
38
|
end
|
37
39
|
|
38
|
-
#
|
40
|
+
# Instruct Logidze to create a full snapshot for the new versions, not a diff
|
39
41
|
#
|
40
42
|
# @example
|
41
43
|
# Logidze.with_full_snapshot { post.touch }
|
@@ -43,6 +45,13 @@ module Logidze
|
|
43
45
|
with_logidze_setting("logidze.full_snapshot", "on") { yield }
|
44
46
|
end
|
45
47
|
|
48
|
+
def on_pending_upgrade=(mode)
|
49
|
+
if %i[raise warn ignore].exclude? mode
|
50
|
+
raise ArgumentError, "Unknown on_pending_upgrade option `#{mode.inspect}`. Expecting :raise, :warn or :ignore"
|
51
|
+
end
|
52
|
+
@on_pending_upgrade = mode
|
53
|
+
end
|
54
|
+
|
46
55
|
private
|
47
56
|
|
48
57
|
def with_logidze_setting(name, value)
|
@@ -59,4 +68,5 @@ module Logidze
|
|
59
68
|
self.associations_versioning = false
|
60
69
|
self.ignore_log_data_by_default = false
|
61
70
|
self.return_self_if_log_data_is_empty = true
|
71
|
+
self.on_pending_upgrade = :ignore
|
62
72
|
end
|
data/lib/logidze/engine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "logidze"
|
4
|
+
require "logidze/utils/check_pending"
|
4
5
|
|
5
6
|
module Logidze
|
6
7
|
class Engine < Rails::Engine # :nodoc:
|
@@ -11,5 +12,13 @@ module Logidze
|
|
11
12
|
ActiveRecord::Base.send :include, Logidze::HasLogidze
|
12
13
|
end
|
13
14
|
end
|
15
|
+
|
16
|
+
initializer "check Logidze function versions" do |app|
|
17
|
+
if config.logidze.on_pending_upgrade != :ignore
|
18
|
+
ActiveSupport.on_load(:active_record) do
|
19
|
+
app.config.app_middleware.use Logidze::Utils::CheckPending
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
14
23
|
end
|
15
24
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./function_definitions"
|
4
|
+
require_relative "./pending_migration_error"
|
5
|
+
|
6
|
+
module Logidze
|
7
|
+
module Utils
|
8
|
+
# This Rack middleware is used to verify that all functions are up to date
|
9
|
+
class CheckPending
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
@needs_check = true
|
13
|
+
@mutex = Mutex.new
|
14
|
+
end
|
15
|
+
|
16
|
+
delegate :connection, to: ActiveRecord::Base
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
@mutex.synchronize do
|
20
|
+
if @needs_check
|
21
|
+
notify_or_raise! if needs_migration?
|
22
|
+
end
|
23
|
+
@needs_check = false
|
24
|
+
end
|
25
|
+
|
26
|
+
@app.call(env)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def notify_or_raise!
|
32
|
+
case Logidze.on_pending_upgrade
|
33
|
+
when :warn
|
34
|
+
warn "\n**************************************************\n"\
|
35
|
+
"⛔️ WARNING: Logidze needs an upgrade and might not work correctly.\n"\
|
36
|
+
"Please, make sure to run `bundle exec rails generate logidze:install --update` "\
|
37
|
+
"and apply generated migration."\
|
38
|
+
"\n**************************************************\n\n"
|
39
|
+
when :raise
|
40
|
+
raise Logidze::Utils::PendingMigrationError, "Logidze needs upgrade. Run `bundle exec rails generate logidze:install --update` and apply generated migration."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def needs_migration?
|
45
|
+
(library_function_versions - pg_function_versions).any?
|
46
|
+
end
|
47
|
+
|
48
|
+
def pg_function_versions
|
49
|
+
Logidze::Utils::FunctionDefinitions.from_db.map { |func| [func.name, func.version] }
|
50
|
+
end
|
51
|
+
|
52
|
+
def library_function_versions
|
53
|
+
@library_function_versions ||= Logidze::Utils::FunctionDefinitions.from_fs.map { |func| [func.name, func.version] }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Logidze
|
4
|
+
module Utils
|
5
|
+
class FuncDef < Struct.new(:name, :version, :signature); end
|
6
|
+
|
7
|
+
module FunctionDefinitions
|
8
|
+
class << self
|
9
|
+
def from_fs
|
10
|
+
function_paths = Dir.glob(File.join(__dir__, "..", "..", "generators", "logidze", "install", "functions", "*.sql"))
|
11
|
+
function_paths.map do |path|
|
12
|
+
name = path.match(/([^\/]+)\.sql/)[1]
|
13
|
+
|
14
|
+
file = File.open(path)
|
15
|
+
header, version_comment = file.readline, file.readline
|
16
|
+
|
17
|
+
signature = parse_signature(header)
|
18
|
+
version = parse_version(version_comment)
|
19
|
+
FuncDef.new(name, version, signature)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def from_db
|
24
|
+
query = <<~SQL
|
25
|
+
SELECT pp.proname, pg_get_functiondef(pp.oid) AS definition
|
26
|
+
FROM pg_proc pp
|
27
|
+
WHERE pp.proname like 'logidze_%'
|
28
|
+
ORDER BY pp.oid;
|
29
|
+
SQL
|
30
|
+
ActiveRecord::Base.connection.execute(query).map do |row|
|
31
|
+
version = parse_version(row["definition"])
|
32
|
+
FuncDef.new(row["proname"], version, nil)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def parse_version(line)
|
39
|
+
line.match(/version:\s+(\d+)/)&.[](1).to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_signature(line)
|
43
|
+
parameters = line.match(/CREATE OR REPLACE FUNCTION\s+[\w_]+\((.*)\)/)[1]
|
44
|
+
parameters.split(/\s*,\s*/).map { |param| param.split(/\s+/, 2).last.sub(/\s+DEFAULT .*$/, "") }.join(", ")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module Logidze
|
6
|
+
module Utils
|
7
|
+
class PendingMigrationError < StandardError
|
8
|
+
if Rails::VERSION::MAJOR >= 6
|
9
|
+
require "active_record"
|
10
|
+
require "active_support/actionable_error"
|
11
|
+
include ActiveSupport::ActionableError
|
12
|
+
|
13
|
+
action "Upgrade Logidze" do
|
14
|
+
Rails::Generators.invoke("logidze:install", ["--update"])
|
15
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate
|
16
|
+
if ActiveRecord::Base.dump_schema_after_migration
|
17
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(
|
18
|
+
ActiveRecord::Base.connection_db_config
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/logidze/version.rb
CHANGED
metadata
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logidze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: railties
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - ">="
|
@@ -172,6 +186,9 @@ files:
|
|
172
186
|
- lib/logidze/ignore_log_data/cast_attribute_patch.rb
|
173
187
|
- lib/logidze/meta.rb
|
174
188
|
- lib/logidze/model.rb
|
189
|
+
- lib/logidze/utils/check_pending.rb
|
190
|
+
- lib/logidze/utils/function_definitions.rb
|
191
|
+
- lib/logidze/utils/pending_migration_error.rb
|
175
192
|
- lib/logidze/version.rb
|
176
193
|
- lib/logidze/versioned_association.rb
|
177
194
|
homepage: http://github.com/palkan/logidze
|