logidze 0.2.1 → 0.2.2

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
  SHA1:
3
- metadata.gz: 437f0707fbb215fbfb5655156b0f2f8450f2aa20
4
- data.tar.gz: 533a010cbc9d240c5c70d565621ace20d571579a
3
+ metadata.gz: fcb9249498ac35c0236653c1209d6395679c4d41
4
+ data.tar.gz: efd95cb463680a5e000f5e2b96dae8d7d1bc7c0a
5
5
  SHA512:
6
- metadata.gz: 419c21e03ba9196ff236bb7d8ea1bc897eaa1e7b8573bff1e1196008113641975341712e2f55d0ea8abb887820c18e0f32b654ee673ea379ef263cdae63ce875
7
- data.tar.gz: 8a885b62f97e4492001ef11a1961556faa0810d976f95fdb44dcb3071a5506622edc798f87aa6dd8fb27e40b46d605dd6adced7aa16e19278d2feb40f20beeb8
6
+ metadata.gz: 9e51780490e139a4a475367527480edd0e3530f7c6bda2ef92d0da2591ac8a4e6f8177d2131b7b4f9563e2db3d4ceb6878e1b3574a6ce14206f7b1e9105ba641
7
+ data.tar.gz: 9922f8494d288bb0fd520abaae87872c3f1f8ceeaa0613689eee7637d8d9c423549a4aa545b09d9ef743213ca3503a2303bdce2ad4f1cb733bef817a19bddb2e
@@ -1,3 +1,7 @@
1
+ # 0.2.2
2
+ - Add `--backfill` option to model migration
3
+ - Handle legacy data (that doesn't have log data)
4
+
1
5
  # 0.2.1
2
6
  - Support both Rails 4 and 5
3
7
 
data/README.md CHANGED
@@ -46,13 +46,19 @@ rails generate logidze:model Post
46
46
  rake db:migrate
47
47
  ```
48
48
 
49
+ This also adds `has_logidze` line to your model, which adds methods for working with logs.
50
+
49
51
  You can provide `limit` option to `generate` to limit the size of the log (by default it's unlimited):
50
52
 
51
53
  ```ruby
52
54
  rails generate logidze:model Post --limit=10
53
55
  ```
54
56
 
55
- This also adds `has_logidze` line to your model, which adds methods for working with logs.
57
+ To backfill table data (i.e. create initial snapshots) add `backfill` option:
58
+
59
+ ```ruby
60
+ rails generate logidze:model Post --backfill
61
+ ```
56
62
 
57
63
  ## Usage
58
64
 
@@ -10,6 +10,51 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
10
10
  SQL
11
11
 
12
12
  execute <<~SQL
13
+ CREATE OR REPLACE FUNCTION logidze_snapshot(item jsonb) RETURNS jsonb AS $body$
14
+ BEGIN
15
+ return json_build_object(
16
+ 'v', 1,
17
+ 'h', jsonb_build_array(
18
+ jsonb_build_object(
19
+ 'ts',
20
+ (extract(epoch from now()) * 1000)::bigint,
21
+ 'v',
22
+ 1,
23
+ 'c',
24
+ item - 'log_data'
25
+ )
26
+ )
27
+ );
28
+ END;
29
+ $body$
30
+ LANGUAGE plpgsql;
31
+
32
+ CREATE OR REPLACE FUNCTION logidze_compact_history(log_data jsonb) RETURNS jsonb AS $body$
33
+ DECLARE
34
+ merged jsonb;
35
+ BEGIN
36
+ merged := jsonb_build_object(
37
+ 'ts',
38
+ log_data#>'{h,1,ts}',
39
+ 'v',
40
+ log_data#>'{h,1,v}',
41
+ 'c',
42
+ (log_data#>'{h,0,c}') || (log_data#>'{h,1,c}')
43
+ );
44
+
45
+ return jsonb_set(
46
+ log_data,
47
+ '{h}',
48
+ jsonb_set(
49
+ log_data->'h',
50
+ '{1}',
51
+ merged
52
+ ) - 0
53
+ );
54
+ END;
55
+ $body$
56
+ LANGUAGE plpgsql;
57
+
13
58
  CREATE OR REPLACE FUNCTION logidze_logger() RETURNS TRIGGER AS $body$
14
59
  DECLARE
15
60
  changes jsonb;
@@ -22,28 +67,18 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
22
67
  iterator integer;
23
68
  item record;
24
69
  BEGIN
25
- ts := (extract(epoch from now()) * 1000)::bigint;
26
70
 
27
71
  IF TG_OP = 'INSERT' THEN
28
- changes := to_jsonb(NEW.*) - 'log_data';
29
- new_v := 1;
30
-
31
- NEW.log_data := json_build_object(
32
- 'v',
33
- 1,
34
- 'h',
35
- jsonb_build_array(
36
- jsonb_build_object(
37
- 'ts',
38
- ts,
39
- 'v',
40
- new_v,
41
- 'c',
42
- changes
43
- )
44
- )
45
- );
72
+
73
+ NEW.log_data := logidze_snapshot(to_jsonb(NEW.*));
74
+
46
75
  ELSIF TG_OP = 'UPDATE' THEN
76
+
77
+ IF OLD.log_data is NULL OR OLD.log_data = '{}'::jsonb THEN
78
+ NEW.log_data := logidze_snapshot(to_jsonb(NEW.*));
79
+ RETURN NEW;
80
+ END IF;
81
+
47
82
  history_limit := TG_ARGV[0];
48
83
  current_version := (NEW.log_data->>'v')::int;
49
84
 
@@ -51,6 +86,8 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
51
86
  RETURN NEW;
52
87
  END IF;
53
88
 
89
+ ts := (extract(epoch from now()) * 1000)::bigint;
90
+
54
91
  IF current_version < (NEW.log_data#>>'{h,-1,v}')::int THEN
55
92
  iterator := 0;
56
93
  FOR item in SELECT * FROM jsonb_array_elements(NEW.log_data->'h')
@@ -95,24 +132,7 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
95
132
  );
96
133
 
97
134
  IF history_limit IS NOT NULL AND history_limit = size THEN
98
- merged := jsonb_build_object(
99
- 'ts',
100
- NEW.log_data#>'{h,1,ts}',
101
- 'v',
102
- NEW.log_data#>'{h,1,v}',
103
- 'c',
104
- (NEW.log_data#>'{h,0,c}') || (NEW.log_data#>'{h,1,c}')
105
- );
106
-
107
- NEW.log_data := jsonb_set(
108
- NEW.log_data,
109
- '{h}',
110
- jsonb_set(
111
- NEW.log_data->'h',
112
- '{1}',
113
- merged
114
- ) - 0
115
- );
135
+ NEW.log_data := logidze_compact_history(NEW.log_data);
116
136
  END IF;
117
137
  END IF;
118
138
 
@@ -125,6 +145,8 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
125
145
 
126
146
  def down
127
147
  execute <<~SQL
148
+ DROP FUNCTION logidze_compact_history(jsonb) CASCADE;
149
+ DROP FUNCTION logidze_snapshot(jsonb) CASCADE;
128
150
  DROP FUNCTION logidze_logger() CASCADE;
129
151
  SQL
130
152
  end
@@ -9,6 +9,9 @@ module Logidze
9
9
 
10
10
  class_option :limit, type: :numeric, optional: true, desc: "Specify history size limit"
11
11
 
12
+ class_option :backfill, type: :boolean, optional: true,
13
+ desc: "Add query to backfill existing records history"
14
+
12
15
  def generate_migration
13
16
  migration_template "migration.rb.erb", "db/migrate/#{migration_file_name}"
14
17
  end
@@ -31,6 +34,10 @@ module Logidze
31
34
  def limit
32
35
  options[:limit]
33
36
  end
37
+
38
+ def backfill
39
+ options[:backfill]
40
+ end
34
41
  end
35
42
 
36
43
  private
@@ -1,6 +1,6 @@
1
1
  class <%= @migration_class_name %> < ActiveRecord::Migration
2
2
  def up
3
- add_column :<%= table_name %>, :log_data, :jsonb, default: '{}', null: false
3
+ add_column :<%= table_name %>, :log_data, :jsonb, default: {}, null: false
4
4
 
5
5
  execute <<-SQL
6
6
  CREATE TRIGGER logidze_on_<%= table_name %>
@@ -8,6 +8,13 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
8
8
  WHEN (current_setting('logidze.disabled') <> 'on')
9
9
  EXECUTE PROCEDURE logidze_logger(<%= limit || '' %>);
10
10
  SQL
11
+
12
+ <% if backfill %>
13
+ execute <<-SQL
14
+ UPDATE <%= table_name %> as t
15
+ SET log_data = logidze_snapshot(to_jsonb(t));
16
+ SQL
17
+ <% end %>
11
18
  end
12
19
 
13
20
  def down
@@ -19,11 +19,9 @@ module Logidze
19
19
  end
20
20
 
21
21
  def self.load(json)
22
- new(json) unless json.nil?
22
+ new(json) if json.present?
23
23
  end
24
24
 
25
- ### Rails 4 ###
26
-
27
25
  def initialize(data)
28
26
  @data = data
29
27
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Logidze
3
- VERSION = "0.2.1"
3
+ VERSION = "0.2.2"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logidze
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-02 00:00:00.000000000 Z
11
+ date: 2016-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails