logidze 0.8.1 → 1.0.0.rc1

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +124 -5
  3. data/LICENSE.txt +1 -1
  4. data/README.md +310 -80
  5. data/lib/generators/logidze/fx_helper.rb +17 -0
  6. data/lib/generators/logidze/inject_sql.rb +18 -0
  7. data/lib/generators/logidze/install/USAGE +6 -1
  8. data/lib/generators/logidze/install/functions/logidze_compact_history.sql +38 -0
  9. data/lib/generators/logidze/install/functions/logidze_filter_keys.sql +27 -0
  10. data/lib/generators/logidze/install/functions/logidze_logger.sql +150 -0
  11. data/lib/generators/logidze/install/functions/logidze_snapshot.sql +24 -0
  12. data/lib/generators/logidze/install/functions/logidze_version.sql +20 -0
  13. data/lib/generators/logidze/install/install_generator.rb +61 -3
  14. data/lib/generators/logidze/install/templates/hstore.rb.erb +1 -1
  15. data/lib/generators/logidze/install/templates/migration.rb.erb +19 -232
  16. data/lib/generators/logidze/install/templates/migration_fx.rb.erb +41 -0
  17. data/lib/generators/logidze/model/model_generator.rb +56 -20
  18. data/lib/generators/logidze/model/templates/migration.rb.erb +57 -36
  19. data/lib/generators/logidze/model/triggers/logidze.sql +6 -0
  20. data/lib/logidze.rb +43 -20
  21. data/lib/logidze/engine.rb +4 -1
  22. data/lib/logidze/has_logidze.rb +12 -3
  23. data/lib/logidze/history.rb +7 -15
  24. data/lib/logidze/history/type.rb +1 -1
  25. data/lib/logidze/history/version.rb +6 -5
  26. data/lib/logidze/ignore_log_data.rb +22 -0
  27. data/lib/logidze/ignore_log_data/cast_attribute_patch.rb +17 -0
  28. data/lib/logidze/meta.rb +44 -17
  29. data/lib/logidze/model.rb +65 -37
  30. data/lib/logidze/version.rb +2 -1
  31. data/lib/logidze/versioned_association.rb +0 -1
  32. metadata +47 -103
  33. data/.gitignore +0 -40
  34. data/.hound.yml +0 -3
  35. data/.rubocop.yml +0 -94
  36. data/.travis.yml +0 -39
  37. data/Gemfile +0 -13
  38. data/Rakefile +0 -28
  39. data/bench/performance/README.md +0 -109
  40. data/bench/performance/diff_bench.rb +0 -36
  41. data/bench/performance/insert_bench.rb +0 -20
  42. data/bench/performance/memory_profile.rb +0 -53
  43. data/bench/performance/setup.rb +0 -308
  44. data/bench/performance/update_bench.rb +0 -36
  45. data/bench/triggers/Makefile +0 -56
  46. data/bench/triggers/Readme.md +0 -58
  47. data/bench/triggers/bench.sql +0 -6
  48. data/bench/triggers/hstore_trigger_setup.sql +0 -38
  49. data/bench/triggers/jsonb_minus_2_setup.sql +0 -47
  50. data/bench/triggers/jsonb_minus_setup.sql +0 -49
  51. data/bench/triggers/keys2_trigger_setup.sql +0 -44
  52. data/bench/triggers/keys_trigger_setup.sql +0 -50
  53. data/bin/console +0 -8
  54. data/bin/setup +0 -9
  55. data/gemfiles/rails42.gemfile +0 -5
  56. data/gemfiles/rails5.gemfile +0 -6
  57. data/gemfiles/rails52.gemfile +0 -6
  58. data/gemfiles/railsmaster.gemfile +0 -7
  59. data/lib/logidze/migration.rb +0 -19
  60. data/logidze.gemspec +0 -33
data/.gitignore DELETED
@@ -1,40 +0,0 @@
1
- # Numerous always-ignore extensions
2
- *.diff
3
- *.err
4
- *.orig
5
- *.log
6
- *.rej
7
- *.swo
8
- *.swp
9
- *.vi
10
- *~
11
- *.sass-cache
12
- *.iml
13
- .idea/
14
-
15
- # Sublime
16
- *.sublime-project
17
- *.sublime-workspace
18
-
19
- # OS or Editor folders
20
- .DS_Store
21
- .cache
22
- .project
23
- .settings
24
- .tmproj
25
- Thumbs.db
26
-
27
- .bundle/
28
- log/*.log
29
- *.gz
30
- pkg/
31
- spec/dummy/db/*.sqlite3
32
- spec/dummy/db/*.sqlite3-journal
33
- spec/dummy/tmp/
34
-
35
- Gemfile.lock
36
- Gemfile.local
37
- .rspec
38
- *.gem
39
- tmp/
40
- coverage/
data/.hound.yml DELETED
@@ -1,3 +0,0 @@
1
- ruby:
2
- enabled: true
3
- config_file: .rubocop.yml
@@ -1,94 +0,0 @@
1
- require:
2
- - rubocop-md
3
-
4
- AllCops:
5
- # Include gemspec and Rakefile
6
- Include:
7
- - 'lib/**/*.rb'
8
- - 'lib/**/*.rake'
9
- - 'spec/**/*.rb'
10
- Exclude:
11
- - 'bin/**/*'
12
- - 'spec/dummy/**/*'
13
- - 'vendor/**/*'
14
- - 'gemfiles/**/*'
15
- - 'tmp/**/*'
16
- - 'bench/**/*'
17
- - 'Rakefile'
18
- - 'Gemfile'
19
- - '*.gemspec'
20
- DisplayCopNames: true
21
- StyleGuideCopsOnly: false
22
- TargetRubyVersion: 2.3
23
-
24
- Naming/AccessorMethodName:
25
- Enabled: false
26
-
27
- Naming/UncommunicativeMethodParamName:
28
- Enabled: false
29
-
30
- Style/TrivialAccessors:
31
- Enabled: false
32
-
33
- Style/Documentation:
34
- Exclude:
35
- - 'spec/**/*.rb'
36
-
37
- Style/StringLiterals:
38
- Enabled: false
39
-
40
- Layout/SpaceInsideStringInterpolation:
41
- EnforcedStyle: no_space
42
-
43
- Style/BlockDelimiters:
44
- Exclude:
45
- - 'spec/**/*.rb'
46
-
47
- Style/PercentLiteralDelimiters:
48
- Enabled: false
49
-
50
- Lint/AmbiguousRegexpLiteral:
51
- Enabled: false
52
-
53
- Lint/MissingCopEnableDirective:
54
- Enabled: false
55
-
56
- Lint/UselessAssignment:
57
- Exclude:
58
- - '**/*.md'
59
-
60
- Metrics/MethodLength:
61
- Exclude:
62
- - 'spec/**/*.rb'
63
-
64
- Metrics/BlockLength:
65
- Exclude:
66
- - 'spec/**/*.rb'
67
-
68
- Metrics/LineLength:
69
- Max: 100
70
- Exclude:
71
- - 'spec/**/*.rb'
72
-
73
- Rails/Date:
74
- Enabled: false
75
-
76
- Rails/TimeZone:
77
- Enabled: false
78
-
79
- Style/NumericLiteralPrefix:
80
- Enabled: false
81
-
82
- Lint/HandleExceptions:
83
- Enabled: true
84
- Exclude:
85
- - 'spec/**/*.rb'
86
-
87
- Layout/DotPosition:
88
- EnforcedStyle: leading
89
-
90
- Layout/IndentHeredoc:
91
- Enabled: false
92
-
93
- Layout/EmptyLineAfterMagicComment:
94
- Enabled: false
@@ -1,39 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
-
4
- dist: trusty
5
- sudo: false
6
-
7
- addons:
8
- postgresql: "9.6"
9
-
10
- env:
11
- global:
12
- - LOGIDZE_DB_USER=postgres
13
- - LOGIDZE_DB_NAME=logidze
14
-
15
- before_script:
16
- - gem update --system
17
- - bundle exec rake dummy:db:create
18
- - psql -U postgres -d logidze -c 'CREATE EXTENSION IF NOT EXISTS hstore;'
19
- - bundle exec rake dummy:db:test:prepare
20
-
21
- matrix:
22
- include:
23
- - rvm: ruby-head
24
- gemfile: gemfiles/railsmaster.gemfile
25
- - rvm: 2.5.0
26
- gemfile: gemfiles/railsmaster.gemfile
27
- - rvm: 2.5.0
28
- gemfile: gemfiles/rails5.gemfile
29
- - rvm: 2.5.1
30
- gemfile: gemfiles/rails52.gemfile
31
- - rvm: 2.4.1
32
- gemfile: gemfiles/rails5.gemfile
33
- - rvm: 2.3.1
34
- gemfile: gemfiles/rails42.gemfile
35
- allow_failures:
36
- - rvm: ruby-head
37
- gemfile: gemfiles/railsmaster.gemfile
38
- - rvm: 2.5.0
39
- gemfile: gemfiles/railsmaster.gemfile
data/Gemfile DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
- source 'https://rubygems.org'
3
-
4
- # Specify your gem's dependencies in logidze.gemspec
5
- gemspec
6
-
7
- local_gemfile = "#{File.dirname(__FILE__)}/Gemfile.local"
8
-
9
- if File.exist?(local_gemfile)
10
- eval(File.read(local_gemfile)) # rubocop:disable Lint/Eval
11
- else
12
- gem 'activerecord', '~> 5.1.1'
13
- end
data/Rakefile DELETED
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- require "bundler/gem_tasks"
3
- require "rspec/core/rake_task"
4
- require "rubocop/rake_task"
5
-
6
- RuboCop::RakeTask.new
7
- RSpec::Core::RakeTask.new(:spec)
8
-
9
- namespace :dummy do
10
- require_relative "spec/dummy/config/application"
11
- Dummy::Application.load_tasks
12
- end
13
-
14
- task(:spec).clear
15
- desc "Run specs other than spec/acceptance"
16
- RSpec::Core::RakeTask.new("spec") do |task|
17
- task.exclude_pattern = "spec/acceptance/**/*_spec.rb"
18
- task.verbose = false
19
- end
20
-
21
- desc "Run acceptance specs in spec/acceptance"
22
- RSpec::Core::RakeTask.new("spec:acceptance") do |task|
23
- task.pattern = "spec/acceptance/**/*_spec.rb"
24
- task.verbose = false
25
- end
26
-
27
- desc "Run the specs and acceptance tests"
28
- task default: %w(rubocop spec spec:acceptance)
@@ -1,109 +0,0 @@
1
- # Performance benchmarks: PaperTail vs. Logidze
2
-
3
- We want to compare Logidze with the most popular versioning library for Rails – PaperTrail.
4
-
5
-
6
- ## Insert ([source](insert_bench.rb))
7
-
8
- ```
9
- PaperTrail INSERT 213.148 (± 8.9%) i/s - 1.060k in 5.018504s
10
- Logidze INSERT 613.387 (±16.3%) i/s - 2.970k in 5.036127s
11
- ```
12
-
13
-
14
- ## Update ([source](update_bench.rb))
15
-
16
- When changeset has 2 fields:
17
-
18
- ```
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
21
- ```
22
-
23
- When changeset has 5 fields:
24
-
25
- ```
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
28
- ```
29
-
30
- ## Getting diff ([source](diff_bench.rb))
31
-
32
- PaperTrail doesn't have built-in method to calculate diff between not adjacent versions.
33
- We add `diff_from(ts)` and `diff_from_joined(ts)` (which uses SQL JOIN) methods to calculate diff from specified version using changesets.
34
-
35
- When each record has 10 versions:
36
-
37
- ```
38
- PT DIFF 20.874 (± 4.8%) i/s - 106.000 in 5.091402s
39
- PT (join) DIFF 20.619 (± 4.8%) i/s - 104.000 in 5.070160s
40
- Logidze DIFF 109.482 (±24.7%) i/s - 500.000 in 5.103534s
41
- ```
42
-
43
- When each record has 100 versions:
44
-
45
- ```
46
- PT DIFF 2.998 (± 0.0%) i/s - 15.000 in 5.019494s
47
- PT (join) DIFF 3.193 (± 0.0%) i/s - 16.000 in 5.030155s
48
- Logidze DIFF 19.627 (±25.5%) i/s - 88.000 in 5.035555s
49
- ```
50
-
51
- And, finally, when each record has 1000 versions:
52
-
53
- ```
54
- PT DIFF 0.270 (± 0.0%) i/s - 17.000 in 63.038374s
55
- PT (join) DIFF 0.235 (± 0.0%) i/s - 14.000 in 60.350886s
56
- Logidze DIFF 2.022 (± 0.0%) i/s - 120.000 in 60.142965s
57
- ```
58
-
59
- ## Select memory usage ([source](memory_profile.rb))
60
-
61
- Logidze loads more data (because it stores log in-place). But how much more?
62
- We consider two cases for PaperTrail: when we want to calculate diff (and thus loading versions) and when we don't need any history related data.
63
-
64
- When each record has 10 versions:
65
-
66
- ```
67
- PT records
68
- Total Allocated: 27.8 KB
69
- Total Retained: 16.59 KB
70
- Retained memory (per record): 2.14 KB
71
-
72
- PT with versions
73
- Total Allocated: 228.01 KB
74
- Total Retained: 170.78 KB
75
- Retained memory (per record): 143.13 KB
76
-
77
- Logidze records
78
- Total Allocated: 46.45 KB
79
- Total Retained: 34.73 KB
80
- Retained memory (per record): 4.11 KB
81
- ```
82
-
83
- When each record has 100 versions:
84
-
85
- ```
86
- PT with versions
87
- Total Allocated: 1.92 MB
88
- Total Retained: 1.56 MB
89
- Retained memory (per record): 1.53 MB
90
-
91
- Logidze records
92
- Total Allocated: 162.48 KB
93
- Total Retained: 150.76 KB
94
- Retained memory (per record): 15.4 KB
95
- ```
96
-
97
- When each record has 1000 versions:
98
-
99
- ```
100
- PT with versions
101
- Total Allocated: 18.23 MB
102
- Total Retained: 14.86 MB
103
- Retained memory (per record): 14.83 MB
104
-
105
- Logidze records
106
- Total Allocated: 1.32 MB
107
- Total Retained: 1.31 MB
108
- Retained memory (per record): 131.59 KB
109
- ```
@@ -1,36 +0,0 @@
1
- require 'benchmark/ips'
2
- require './setup'
3
-
4
- # How many records do you want?
5
- N = (ENV['N'] || '100').to_i
6
-
7
- # How many version each record has?
8
- V = (ENV['V'] || '10').to_i
9
-
10
- # Benchmark run time
11
- BM_TIME = (ENV['BM_TIME'] || 5).to_i
12
-
13
- BM_WARMUP = [(BM_TIME / 10), 2].max
14
-
15
- LogidzeBench.cleanup
16
- LogidzeBench.populate(N)
17
-
18
- ts1 = LogidzeBench.generate_versions(V/2)
19
-
20
- LogidzeBench.generate_versions(V/2)
21
-
22
- Benchmark.ips do |x|
23
- x.config(time: BM_TIME, warmup: BM_WARMUP)
24
-
25
- x.report('PT DIFF') do
26
- User.random(N/2).diff_from(ts1)
27
- end
28
-
29
- x.report('PT (join) DIFF') do
30
- User.random(N/2).diff_from_joined(ts1)
31
- end
32
-
33
- x.report('Logidze DIFF') do
34
- LogidzeUser.random(N/2).diff_from(ts1)
35
- end
36
- end
@@ -1,20 +0,0 @@
1
- require 'benchmark/ips'
2
- require './setup'
3
-
4
- params = {
5
- email: Faker::Internet.email,
6
- position: Faker::Number.number(3),
7
- name: Faker::Name.name,
8
- age: Faker::Number.number(2),
9
- bio: Faker::Lorem.paragraph
10
- }
11
-
12
- Benchmark.ips do |x|
13
- x.report('PaperTrail INSERT') do
14
- User.create!(params)
15
- end
16
-
17
- x.report('Logidze INSERT') do
18
- LogidzeUser.create!(params)
19
- end
20
- end
@@ -1,53 +0,0 @@
1
- require './setup'
2
- require 'active_support/core_ext'
3
- require 'memory_profiler'
4
-
5
- # How many records do you want?
6
- N = (ENV['N'] || '10').to_i
7
-
8
- # How many version each record has?
9
- V = (ENV['V'] || '10').to_i
10
-
11
- LogidzeBench.cleanup
12
- LogidzeBench.populate(N)
13
- LogidzeBench.generate_versions(V)
14
-
15
- module MemoryReport
16
- KILO_BYTE = 1024
17
- MEGA_BYTE = 1024 * 1024
18
-
19
- module_function
20
- def call(msg, relation)
21
- buffer = nil
22
- delta = N / 10
23
- r0 = MemoryProfiler.report do
24
- buffer = relation.random(N - delta).to_a
25
- end
26
-
27
- buffer = nil
28
- r1 = MemoryProfiler.report do
29
- buffer = relation.to_a
30
- end
31
-
32
- $stdout.puts msg
33
- $stdout.puts "Total Allocated:\t\t\t\t#{to_human_size(r1.total_allocated_memsize)}"
34
- $stdout.puts "Total Retained:\t\t\t\t\t#{to_human_size(r1.total_retained_memsize)}"
35
- $stdout.puts "Retained_memsize memory (per record):\t\t#{to_human_size((r1.total_retained_memsize - r0.total_retained_memsize) / delta)}"
36
- end
37
-
38
- module_function
39
- def to_human_size(size)
40
- if size > MEGA_BYTE
41
- "#{(size.to_f / MEGA_BYTE).round(2)} MB"
42
- elsif size > KILO_BYTE
43
- "#{(size.to_f / KILO_BYTE).round(2)} KB"
44
- else
45
- "#{size} B"
46
- end
47
- end
48
- end
49
-
50
-
51
- MemoryReport.("PT records", User.all)
52
- MemoryReport.("PT with versions", User.joins(:versions).all)
53
- MemoryReport.("Logidze records", LogidzeUser.all)