logidze 0.9.0 → 0.10.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +3 -0
  3. data/.github/ISSUE_TEMPLATE.md +20 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +29 -0
  5. data/.rubocop.yml +30 -69
  6. data/.travis.yml +8 -5
  7. data/CHANGELOG.md +35 -1
  8. data/Gemfile +2 -0
  9. data/LICENSE.txt +1 -1
  10. data/README.md +67 -26
  11. data/Rakefile +2 -2
  12. data/assets/pg_log_data_chart.png +0 -0
  13. data/bench/performance/README.md +2 -2
  14. data/bench/performance/diff_bench.rb +15 -13
  15. data/bench/performance/insert_bench.rb +6 -4
  16. data/bench/performance/memory_profile.rb +12 -9
  17. data/bench/performance/setup.rb +35 -28
  18. data/bench/performance/update_bench.rb +8 -6
  19. data/bin/setup +2 -2
  20. data/gemfiles/rails42.gemfile +1 -0
  21. data/gemfiles/rails6.gemfile +6 -0
  22. data/lib/generators/logidze/install/install_generator.rb +3 -2
  23. data/lib/generators/logidze/model/model_generator.rb +12 -12
  24. data/lib/logidze.rb +44 -18
  25. data/lib/logidze/engine.rb +2 -1
  26. data/lib/logidze/has_logidze.rb +14 -4
  27. data/lib/logidze/history.rb +6 -5
  28. data/lib/logidze/history/type.rb +1 -1
  29. data/lib/logidze/history/version.rb +6 -5
  30. data/lib/logidze/ignore_log_data.rb +31 -4
  31. data/lib/logidze/ignore_log_data/association.rb +11 -0
  32. data/lib/logidze/ignore_log_data/default_scope_patch.rb +25 -0
  33. data/lib/logidze/ignore_log_data/ignored_columns.rb +1 -1
  34. data/lib/logidze/ignore_log_data/missing_attribute_patch.rb +3 -1
  35. data/lib/logidze/meta.rb +1 -1
  36. data/lib/logidze/migration.rb +1 -0
  37. data/lib/logidze/model.rb +14 -4
  38. data/lib/logidze/version.rb +2 -1
  39. data/lib/logidze/versioned_association.rb +0 -1
  40. data/logidze.gemspec +16 -8
  41. metadata +28 -60
  42. data/.hound.yml +0 -3
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require "bundler/gem_tasks"
2
+
3
3
  require "rspec/core/rake_task"
4
4
  require "rubocop/rake_task"
5
5
 
@@ -25,4 +25,4 @@ RSpec::Core::RakeTask.new("spec:acceptance") do |task|
25
25
  end
26
26
 
27
27
  desc "Run the specs and acceptance tests"
28
- task default: %w(rubocop spec spec:acceptance)
28
+ task default: %w[rubocop spec spec:acceptance]
Binary file
@@ -17,14 +17,14 @@ When changeset has 2 fields:
17
17
 
18
18
  ```
19
19
  PaperTrail UPDATE #1 256.651 (±26.5%) i/s - 1.206k in 5.002300s
20
- Logidze UPDATE #1 356.932 (±12.6%) i/s - 1.764k in 5.030560s
20
+ Logidze UPDATE #1 356.932 (±12.6%) i/s - 1.764k in 5.030560s
21
21
  ```
22
22
 
23
23
  When changeset has 5 fields:
24
24
 
25
25
  ```
26
26
  PaperTrail UPDATE #2 246.281 (±24.0%) i/s - 1.168k in 5.008234s
27
- Logidze UPDATE #2 331.942 (±16.6%) i/s - 1.593k in 5.028135s
27
+ Logidze UPDATE #2 331.942 (±16.6%) i/s - 1.593k in 5.028135s
28
28
  ```
29
29
 
30
30
  ## Getting diff ([source](diff_bench.rb))
@@ -1,36 +1,38 @@
1
- require 'benchmark/ips'
2
- require './setup'
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark/ips"
4
+ require "./setup"
3
5
 
4
6
  # How many records do you want?
5
- N = (ENV['N'] || '100').to_i
7
+ N = (ENV["N"] || "100").to_i
6
8
 
7
9
  # How many version each record has?
8
- V = (ENV['V'] || '10').to_i
10
+ V = (ENV["V"] || "10").to_i
9
11
 
10
12
  # Benchmark run time
11
- BM_TIME = (ENV['BM_TIME'] || 5).to_i
13
+ BM_TIME = (ENV["BM_TIME"] || 5).to_i
12
14
 
13
15
  BM_WARMUP = [(BM_TIME / 10), 2].max
14
16
 
15
17
  LogidzeBench.cleanup
16
18
  LogidzeBench.populate(N)
17
19
 
18
- ts1 = LogidzeBench.generate_versions(V/2)
20
+ ts1 = LogidzeBench.generate_versions(V / 2)
19
21
 
20
- LogidzeBench.generate_versions(V/2)
22
+ LogidzeBench.generate_versions(V / 2)
21
23
 
22
24
  Benchmark.ips do |x|
23
25
  x.config(time: BM_TIME, warmup: BM_WARMUP)
24
26
 
25
- x.report('PT DIFF') do
26
- User.random(N/2).diff_from(ts1)
27
+ x.report("PT DIFF") do
28
+ User.random(N / 2).diff_from(ts1)
27
29
  end
28
30
 
29
- x.report('PT (join) DIFF') do
30
- User.random(N/2).diff_from_joined(ts1)
31
+ x.report("PT (join) DIFF") do
32
+ User.random(N / 2).diff_from_joined(ts1)
31
33
  end
32
34
 
33
- x.report('Logidze DIFF') do
34
- LogidzeUser.random(N/2).diff_from(ts1)
35
+ x.report("Logidze DIFF") do
36
+ LogidzeUser.random(N / 2).diff_from(ts1)
35
37
  end
36
38
  end
@@ -1,5 +1,7 @@
1
- require 'benchmark/ips'
2
- require './setup'
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark/ips"
4
+ require "./setup"
3
5
 
4
6
  params = {
5
7
  email: Faker::Internet.email,
@@ -10,11 +12,11 @@ params = {
10
12
  }
11
13
 
12
14
  Benchmark.ips do |x|
13
- x.report('PaperTrail INSERT') do
15
+ x.report("PaperTrail INSERT") do
14
16
  User.create!(params)
15
17
  end
16
18
 
17
- x.report('Logidze INSERT') do
19
+ x.report("Logidze INSERT") do
18
20
  LogidzeUser.create!(params)
19
21
  end
20
22
  end
@@ -1,12 +1,14 @@
1
- require './setup'
2
- require 'active_support/core_ext'
3
- require 'memory_profiler'
1
+ # frozen_string_literal: true
2
+
3
+ require "./setup"
4
+ require "active_support/core_ext"
5
+ require "memory_profiler"
4
6
 
5
7
  # How many records do you want?
6
- N = (ENV['N'] || '10').to_i
8
+ N = (ENV["N"] || "10").to_i
7
9
 
8
10
  # How many version each record has?
9
- V = (ENV['V'] || '10').to_i
11
+ V = (ENV["V"] || "10").to_i
10
12
 
11
13
  LogidzeBench.cleanup
12
14
  LogidzeBench.populate(N)
@@ -17,6 +19,7 @@ module MemoryReport
17
19
  MEGA_BYTE = 1024 * 1024
18
20
 
19
21
  module_function
22
+
20
23
  def call(msg, relation)
21
24
  buffer = nil
22
25
  delta = N / 10
@@ -36,6 +39,7 @@ module MemoryReport
36
39
  end
37
40
 
38
41
  module_function
42
+
39
43
  def to_human_size(size)
40
44
  if size > MEGA_BYTE
41
45
  "#{(size.to_f / MEGA_BYTE).round(2)} MB"
@@ -47,7 +51,6 @@ module MemoryReport
47
51
  end
48
52
  end
49
53
 
50
-
51
- MemoryReport.("PT records", User.all)
52
- MemoryReport.("PT with versions", User.joins(:versions).all)
53
- MemoryReport.("Logidze records", LogidzeUser.all)
54
+ MemoryReport.call("PT records", User.all)
55
+ MemoryReport.call("PT with versions", User.joins(:versions).all)
56
+ MemoryReport.call("Logidze records", LogidzeUser.all)
@@ -1,22 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'bundler/inline'
4
+ require "bundler/inline"
3
5
  rescue LoadError => e
4
- $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
6
+ warn "Bundler version 1.10 or later is required. Please update your Bundler"
5
7
  raise e
6
8
  end
7
9
 
8
10
  gemfile(true) do
9
- source 'https://rubygems.org'
10
- gem 'activerecord', '~>4.2'
11
- gem 'pg'
12
- gem 'paper_trail', '~>4.2', require: false
13
- gem 'pry-byebug'
14
- gem 'faker'
15
- gem 'benchmark-ips'
16
- gem 'memory_profiler'
11
+ source "https://rubygems.org"
12
+ gem "activerecord", "~>4.2"
13
+ gem "pg"
14
+ gem "paper_trail", "~>4.2", require: false
15
+ gem "pry-byebug"
16
+ gem "faker"
17
+ gem "benchmark-ips"
18
+ gem "memory_profiler"
17
19
  end
18
20
 
19
- DB_NAME = ENV['DB_NAME'] || 'logidze_query_bench'
21
+ DB_NAME = ENV["DB_NAME"] || "logidze_query_bench"
20
22
 
21
23
  begin
22
24
  system("createdb #{DB_NAME}")
@@ -24,24 +26,25 @@ rescue
24
26
  $stdout.puts "DB already exists"
25
27
  end
26
28
 
27
- $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
29
+ $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
28
30
 
29
- require 'active_record'
30
- require 'logger'
31
- require 'logidze'
31
+ require "active_record"
32
+ require "logger"
33
+ require "logidze"
32
34
 
33
35
  ActiveRecord::Base.send :include, Logidze::HasLogidze
34
36
 
35
- ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: DB_NAME)
37
+ ActiveRecord::Base.establish_connection(adapter: "postgresql", database: DB_NAME)
36
38
 
37
39
  at_exit do
38
40
  ActiveRecord::Base.connection.disconnect!
39
41
  end
40
42
 
41
- require 'paper_trail'
43
+ require "paper_trail"
42
44
 
43
45
  module LogidzeBench
44
46
  module_function
47
+
45
48
  def setup_db
46
49
  ActiveRecord::Schema.define do
47
50
  # PaperTrail setup
@@ -171,7 +174,7 @@ module LogidzeBench
171
174
  jsonb_set(
172
175
  NEW.log_data->'h',
173
176
  '{1}',
174
- merged
177
+ merged
175
178
  ) - 0
176
179
  );
177
180
  END IF;
@@ -198,7 +201,7 @@ module LogidzeBench
198
201
  t.string :name
199
202
  t.text :bio
200
203
  t.integer :age
201
- t.jsonb :log_data, default: '{}', null: false
204
+ t.jsonb :log_data, default: "{}", null: false
202
205
  t.timestamps
203
206
  end
204
207
 
@@ -212,6 +215,7 @@ module LogidzeBench
212
215
  end
213
216
 
214
217
  module_function
218
+
215
219
  def populate(n = 1_000)
216
220
  n.times do
217
221
  params = fake_params
@@ -221,6 +225,7 @@ module LogidzeBench
221
225
  end
222
226
 
223
227
  module_function
228
+
224
229
  def cleanup
225
230
  LogidzeUser.delete_all
226
231
  User.delete_all
@@ -228,8 +233,9 @@ module LogidzeBench
228
233
  end
229
234
 
230
235
  module_function
236
+
231
237
  def generate_versions(num = 1)
232
- num.times do
238
+ num.times do
233
239
  User.find_each do |u|
234
240
  u.update!(fake_params(sample: true))
235
241
  end
@@ -245,6 +251,7 @@ module LogidzeBench
245
251
  end
246
252
 
247
253
  module_function
254
+
248
255
  def fake_params(sample: false)
249
256
  params = {
250
257
  email: Faker::Internet.email,
@@ -254,14 +261,14 @@ module LogidzeBench
254
261
  bio: Faker::Lorem.paragraph
255
262
  }
256
263
 
257
- return params.slice(%i(email position name age bio).sample) if sample
264
+ return params.slice(%i[email position name age bio].sample) if sample
258
265
  params
259
266
  end
260
267
  end
261
268
 
262
269
  module ARandom
263
270
  def random(num = 1)
264
- rel = order('random()')
271
+ rel = order("random()")
265
272
  num == 1 ? rel.first : rel.limit(num)
266
273
  end
267
274
  end
@@ -271,11 +278,11 @@ class User < ActiveRecord::Base
271
278
  has_paper_trail
272
279
 
273
280
  def self.diff_from(ts)
274
- includes(:versions).map { |u| { 'id' => u.id, 'changes' => u.diff_from(ts) } }
281
+ includes(:versions).map { |u| {"id" => u.id, "changes" => u.diff_from(ts)} }
275
282
  end
276
283
 
277
284
  def self.diff_from_joined(ts)
278
- eager_load(:versions).map { |u| { 'id' => u.id, 'changes' => u.diff_from(ts) } }
285
+ eager_load(:versions).map { |u| {"id" => u.id, "changes" => u.diff_from(ts)} }
279
286
  end
280
287
 
281
288
  def diff_from(ts)
@@ -290,11 +297,11 @@ class User < ActiveRecord::Base
290
297
  private
291
298
 
292
299
  def merge_changeset(acc, data)
293
- data.each do |k,v|
300
+ data.each do |k, v|
294
301
  unless acc.key?(k)
295
- acc[k] = { 'old' => v[0] }
302
+ acc[k] = {"old" => v[0]}
296
303
  end
297
- acc[k]['new'] = v[1]
304
+ acc[k]["new"] = v[1]
298
305
  end
299
306
  end
300
307
  end
@@ -305,4 +312,4 @@ class LogidzeUser < ActiveRecord::Base
305
312
  end
306
313
 
307
314
  # Run migration only if neccessary
308
- LogidzeBench.setup_db if ENV['FORCE'].present? || !ActiveRecord::Base.connection.tables.include?('logidze_users')
315
+ LogidzeBench.setup_db if ENV["FORCE"].present? || !ActiveRecord::Base.connection.tables.include?("logidze_users")
@@ -1,5 +1,7 @@
1
- require 'benchmark/ips'
2
- require './setup'
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark/ips"
4
+ require "./setup"
3
5
 
4
6
  params = {
5
7
  age: Faker::Number.number(2),
@@ -18,19 +20,19 @@ LogidzeBench.cleanup
18
20
  LogidzeBench.populate
19
21
 
20
22
  Benchmark.ips do |x|
21
- x.report('PT UPDATE #1') do
23
+ x.report("PT UPDATE #1") do
22
24
  User.random.update!(params)
23
25
  end
24
26
 
25
- x.report('Logidze UPDATE #1') do
27
+ x.report("Logidze UPDATE #1") do
26
28
  LogidzeUser.random.update!(params)
27
29
  end
28
30
 
29
- x.report('PT UPDATE #2') do
31
+ x.report("PT UPDATE #2") do
30
32
  User.random.update!(params2)
31
33
  end
32
34
 
33
- x.report('Logidze UPDATE #2') do
35
+ x.report("Logidze UPDATE #2") do
34
36
  LogidzeUser.random.update!(params2)
35
37
  end
36
38
  end
data/bin/setup CHANGED
@@ -5,5 +5,5 @@ set -e
5
5
  gem install bundler --conservative
6
6
  bundle check || bundle install
7
7
 
8
- bundle exec rake dummy:db:create
9
- bundle exec rake dummy:db:test:prepare
8
+ RAILS_ENV=test bundle exec rake dummy:db:create
9
+ RAILS_ENV=test bundle exec rake dummy:db:migrate
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'rails', '~> 4.2'
4
+ gem 'pg', '~> 0.18'
4
5
 
5
6
  gemspec path: '..'
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '6.0.0.rc1'
4
+ gem 'rspec-rails', '>= 3.5'
5
+
6
+ gemspec path: '..'
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "rails/generators"
3
4
  require "rails/generators/active_record"
4
5
 
@@ -7,7 +8,7 @@ module Logidze
7
8
  class InstallGenerator < ::Rails::Generators::Base # :nodoc:
8
9
  include Rails::Generators::Migration
9
10
 
10
- source_root File.expand_path('templates', __dir__)
11
+ source_root File.expand_path("templates", __dir__)
11
12
 
12
13
  class_option :update, type: :boolean, optional: true,
13
14
  desc: "Define whether this is an update migration"
@@ -25,7 +26,7 @@ module Logidze
25
26
  no_tasks do
26
27
  def migration_name
27
28
  if update?
28
- "logidze_update_#{Logidze::VERSION.delete('.')}"
29
+ "logidze_update_#{Logidze::VERSION.delete(".")}"
29
30
  else
30
31
  "logidze_install"
31
32
  end
@@ -1,12 +1,12 @@
1
- # rubocop:disable Metrics/BlockLength
2
1
  # frozen_string_literal: true
2
+
3
3
  require "rails/generators"
4
4
  require "rails/generators/active_record/migration/migration_generator"
5
5
 
6
6
  module Logidze
7
7
  module Generators
8
8
  class ModelGenerator < ::ActiveRecord::Generators::Base # :nodoc:
9
- source_root File.expand_path('templates', __dir__)
9
+ source_root File.expand_path("templates", __dir__)
10
10
 
11
11
  class_option :limit, type: :numeric, optional: true, desc: "Specify history size limit"
12
12
 
@@ -77,17 +77,17 @@ module Logidze
77
77
 
78
78
  def columns_blacklist
79
79
  array = if !options[:whitelist]
80
- options[:blacklist]
81
- else
82
- class_name.constantize.column_names - options[:whitelist]
83
- end
80
+ options[:blacklist]
81
+ else
82
+ class_name.constantize.column_names - options[:whitelist]
83
+ end
84
84
 
85
85
  format_pgsql_array(array)
86
86
  end
87
87
 
88
88
  def timestamp_column
89
- value = options[:timestamp_column] || 'updated_at'
90
- return if %w(nil null false).include?(value)
89
+ value = options[:timestamp_column] || "updated_at"
90
+ return if %w[nil null false].include?(value)
91
91
 
92
92
  escape_pgsql_string(value)
93
93
  end
@@ -101,13 +101,13 @@ module Logidze
101
101
  end
102
102
 
103
103
  def logidze_snapshot_parameters
104
- format_pgsql_args('to_jsonb(t)', timestamp_column, columns_blacklist)
104
+ format_pgsql_args("to_jsonb(t)", timestamp_column, columns_blacklist)
105
105
  end
106
106
 
107
107
  def format_pgsql_array(ruby_array)
108
108
  return if ruby_array.blank?
109
109
 
110
- "'{" + ruby_array.join(', ') + "}'"
110
+ "'{" + ruby_array.join(", ") + "}'"
111
111
  end
112
112
 
113
113
  def escape_pgsql_string(string)
@@ -124,10 +124,10 @@ module Logidze
124
124
  def format_pgsql_args(*values)
125
125
  args = []
126
126
  values.reverse_each do |value|
127
- formatted_value = value.presence || (args.any? && 'null')
127
+ formatted_value = value.presence || (args.any? && "null")
128
128
  args << formatted_value if formatted_value
129
129
  end
130
- args.compact.reverse.join(', ')
130
+ args.compact.reverse.join(", ")
131
131
  end
132
132
  end
133
133