logidze 0.5.3 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a553a435446577ff945a979411dcd5d36c6185e7
4
- data.tar.gz: 4c06374961f3073969d5f7d16184bd7e7e8d5dd9
3
+ metadata.gz: eac2c78af58349b132099e71a9a3f6b780a432c5
4
+ data.tar.gz: cab59c998349bb26b5affe84574bfc5509243542
5
5
  SHA512:
6
- metadata.gz: 9bbdf6fcec9cb2e4a5686f7f80972aa43889bda5e74e7711d4e80364d580279e9f947859aa76342b3018dcf5fcc471ab6b998c5a54e9b836654dab1e94e9bdeb
7
- data.tar.gz: 991804f34a2f90601794418789fde42aff8d7031a8edd6b115fb79c4e0fd59e3b14277b8931a509e19c01200d4cd830776484e6d4622059c4bca3b321d2ecfc7
6
+ metadata.gz: acd1debc4bc436ae1e1142dd2d760c7a614f9ea6be8e46f751a2497ebbdc2d8054243f3a05d0e00aa0b07a243762ece3834a78f77b744fc9c96ee62da53fac87
7
+ data.tar.gz: 756bebbaac83f9bb0d205b7208c43424cdbdda32e054e1a978839dff72441ce9083e88f870919bf475eac1cb2b70727bc0f40b93dc4f954bdedb1fddc5b41fbe
data/.rubocop.yml CHANGED
@@ -9,11 +9,14 @@ AllCops:
9
9
  - 'spec/dummy/**/*'
10
10
  - 'tmp/**/*'
11
11
  - 'bench/**/*'
12
+ - 'Rakefile'
13
+ - 'Gemfile'
14
+ - '*.gemspec'
12
15
  DisplayCopNames: true
13
16
  StyleGuideCopsOnly: false
14
17
  TargetRubyVersion: 2.3
15
18
 
16
- Style/AccessorMethodName:
19
+ Naming/AccessorMethodName:
17
20
  Enabled: false
18
21
 
19
22
  Style/TrivialAccessors:
@@ -26,20 +29,30 @@ Style/Documentation:
26
29
  Style/StringLiterals:
27
30
  Enabled: false
28
31
 
29
- Style/SpaceInsideStringInterpolation:
32
+ Layout/SpaceInsideStringInterpolation:
30
33
  EnforcedStyle: no_space
31
34
 
32
35
  Style/BlockDelimiters:
33
36
  Exclude:
34
37
  - 'spec/**/*.rb'
35
38
 
39
+ Style/PercentLiteralDelimiters:
40
+ Enabled: false
41
+
36
42
  Lint/AmbiguousRegexpLiteral:
37
43
  Enabled: false
38
44
 
45
+ Lint/MissingCopEnableDirective:
46
+ Enabled: false
47
+
39
48
  Metrics/MethodLength:
40
49
  Exclude:
41
50
  - 'spec/**/*.rb'
42
51
 
52
+ Metrics/BlockLength:
53
+ Exclude:
54
+ - 'spec/**/*.rb'
55
+
43
56
  Metrics/LineLength:
44
57
  Max: 100
45
58
  Exclude:
@@ -59,5 +72,11 @@ Lint/HandleExceptions:
59
72
  Exclude:
60
73
  - 'spec/**/*.rb'
61
74
 
62
- Style/DotPosition:
75
+ Layout/DotPosition:
63
76
  EnforcedStyle: leading
77
+
78
+ Layout/IndentHeredoc:
79
+ Enabled: false
80
+
81
+ Layout/EmptyLineAfterMagicComment:
82
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.6.0 (2017-12-27)
6
+
7
+ - [Fixes [#33](https://github.com/palkan/logidze/issues/33)] Support attributes types. ([@palkan][])
8
+
9
+ Added deserialization of complex types (such as `jsonb`, arrays, whatever).
10
+
11
+ - Use positional arguments in `at`/`diff_from` methods and allow passing version. ([@palkan][])
12
+
13
+ Now you can write `post.diff_from(time: ts)`, `post.diff_from(version: x)`, Post.at(time: 1.day.ago)`, etc.
14
+
15
+ NOTE: the previous behaviour is still supported (but gonna be deprecated),
16
+ i.e. you still can use `post.diff_from(ts)` if you don't mind the deprecation warning.
17
+
5
18
  ## 0.5.3 (2017-08-22)
6
19
 
7
20
  - Add `--update` flag to model migration. ([@palkan][])
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  # Specify your gem's dependencies in logidze.gemspec
data/README.md CHANGED
@@ -134,35 +134,35 @@ post.log_version #=> 3
134
134
  post.log_size #=> 3
135
135
 
136
136
  # Get copy of a record at a given time
137
- old_post = post.at(2.days.ago)
137
+ old_post = post.at(time: 2.days.ago)
138
138
 
139
139
  # or revert the record itself to the previous state (without committing to DB)
140
- post.at!('201-04-15 12:00:00')
140
+ post.at!(time: '201-04-15 12:00:00')
141
141
 
142
142
  # If no version found
143
- post.at('1945-05-09 09:00:00') #=> nil
143
+ post.at(time: '1945-05-09 09:00:00') #=> nil
144
144
  ```
145
145
 
146
146
  You can also get revision by version number:
147
147
 
148
148
  ```ruby
149
- post.at_version(2)
149
+ post.at(version: 2)
150
150
  ```
151
151
 
152
152
  It is also possible to get version for relations:
153
153
 
154
154
  ```ruby
155
- Post.where(active: true).at(1.month.ago)
155
+ Post.where(active: true).at(time: 1.month.ago)
156
156
  ```
157
157
 
158
158
  You can also get diff from specified time:
159
159
 
160
160
  ```ruby
161
- post.diff_from(1.hour.ago)
161
+ post.diff_from(time: 1.hour.ago)
162
162
  #=> { "id" => 27, "changes" => { "title" => { "old" => "Logidze sucks!", "new" => "Logidze rulz!" } } }
163
163
 
164
164
  # the same for relations
165
- Post.where(created_at: Time.zone.today.all_day).diff_from(1.hour.ago)
165
+ Post.where(created_at: Time.zone.today.all_day).diff_from(time: 1.hour.ago)
166
166
  ```
167
167
 
168
168
  There are also `#undo!` and `#redo!` options (and more general `#switch_to!`):
data/Rakefile CHANGED
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  require "bundler/gem_tasks"
2
3
  require "rspec/core/rake_task"
4
+ require "rubocop/rake_task"
3
5
 
6
+ RuboCop::RakeTask.new
4
7
  RSpec::Core::RakeTask.new(:spec)
5
8
 
6
9
  namespace :dummy do
@@ -29,7 +29,7 @@ module Logidze
29
29
 
30
30
  def generate_migration
31
31
  if options[:blacklist] && options[:whitelist]
32
- $stderr.puts "Use only one: --whitelist or --blacklist"
32
+ warn "Use only one: --whitelist or --blacklist"
33
33
  exit(1)
34
34
  end
35
35
  migration_template "migration.rb.erb", "db/migrate/#{migration_file_name}"
@@ -9,7 +9,7 @@ module Logidze
9
9
  module ClassMethods # :nodoc:
10
10
  # Include methods to work with history.
11
11
  #
12
- # rubocop:disable Style/PredicateName
12
+ # rubocop:disable Naming/PredicateName, Style/MixinUsage
13
13
  def has_logidze
14
14
  include Logidze::Model
15
15
  end
@@ -124,8 +124,8 @@ module Logidze
124
124
  private
125
125
 
126
126
  def build_changes(a, b)
127
- b.each_with_object({}) do |kv, acc|
128
- acc[kv.first] = { "old" => a[kv.first], "new" => kv.last } unless kv.last == a[kv.first]
127
+ b.each_with_object({}) do |(k, v), acc|
128
+ acc[k] = { "old" => a[k], "new" => v } unless v == a[k]
129
129
  end
130
130
  end
131
131
 
data/lib/logidze/model.rb CHANGED
@@ -2,7 +2,17 @@
2
2
  require 'active_support'
3
3
 
4
4
  module Logidze
5
+ module Deprecations # :nodoc:
6
+ def self.show_ts_deprecation_for(meth)
7
+ warn(
8
+ "[Deprecation] Usage of #{meth}(time) will be removed in the future releases, "\
9
+ "use #{meth}(time: ts) instead"
10
+ )
11
+ end
12
+ end
13
+
5
14
  # Extends model with methods to browse history
15
+ # rubocop: disable Metrics/ModuleLength
6
16
  module Model
7
17
  require 'logidze/history/type' if Rails::VERSION::MAJOR >= 5
8
18
 
@@ -20,13 +30,17 @@ module Logidze
20
30
 
21
31
  module ClassMethods # :nodoc:
22
32
  # Return records reverted to specified time
23
- def at(ts)
24
- all.map { |record| record.at(ts) }.compact
33
+ def at(ts = nil, time: nil, version: nil)
34
+ Deprecations.show_ts_deprecation_for(".at") if ts
35
+ time ||= ts
36
+ all.map { |record| record.at(time: time, version: version) }.compact
25
37
  end
26
38
 
27
39
  # Return changes made to records since specified time
28
- def diff_from(ts)
29
- all.map { |record| record.diff_from(ts) }
40
+ def diff_from(ts = nil, time: nil, version: nil)
41
+ Deprecations.show_ts_deprecation_for(".diff_from") if ts
42
+ time ||= ts
43
+ all.map { |record| record.diff_from(time: time, version: version) }
30
44
  end
31
45
 
32
46
  # Alias for Logidze.without_logging
@@ -34,9 +48,11 @@ module Logidze
34
48
  Logidze.without_logging(&block)
35
49
  end
36
50
 
51
+ # rubocop: disable Naming/PredicateName
37
52
  def has_logidze?
38
53
  true
39
54
  end
55
+ # rubocop: enable Naming/PredicateName
40
56
  end
41
57
 
42
58
  # Use this to convert Ruby time to milliseconds
@@ -45,35 +61,48 @@ module Logidze
45
61
  attr_accessor :logidze_requested_ts
46
62
 
47
63
  # Return a dirty copy of record at specified time
48
- # If time is less then the first version, then return nil.
49
- # If time is greater then the last version, then return self.
50
- def at(ts)
51
- ts = parse_time(ts)
64
+ # If time/version is less then the first version, then return nil.
65
+ # If time/version is greater then the last version, then return self.
66
+ # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
67
+ def at(ts = nil, time: nil, version: nil)
68
+ Deprecations.show_ts_deprecation_for("#at") if ts
52
69
 
53
- return nil unless log_data.exists_ts?(ts)
70
+ return at_version(version) if version
54
71
 
55
- if log_data.current_ts?(ts)
56
- self.logidze_requested_ts = ts
72
+ time ||= ts
73
+ time = parse_time(time)
74
+
75
+ return nil unless log_data.exists_ts?(time)
76
+
77
+ if log_data.current_ts?(time)
78
+ self.logidze_requested_ts = time
57
79
  return self
58
80
  end
59
81
 
60
- version = log_data.find_by_time(ts).version
82
+ version = log_data.find_by_time(time).version
61
83
 
62
84
  object_at = dup
63
85
  object_at.apply_diff(version, log_data.changes_to(version: version))
64
86
  object_at.id = id
65
- object_at.logidze_requested_ts = ts
87
+ object_at.logidze_requested_ts = time
66
88
 
67
89
  object_at
68
90
  end
91
+ # rubocop: enable Metrics/AbcSize, Metrics/MethodLength
69
92
 
70
93
  # Revert record to the version at specified time (without saving to DB)
71
- def at!(ts)
72
- ts = parse_time(ts)
73
- return self if log_data.current_ts?(ts)
74
- return false unless log_data.exists_ts?(ts)
94
+ def at!(ts = nil, time: nil, version: nil)
95
+ Deprecations.show_ts_deprecation_for("#at!") if ts
96
+
97
+ return at_version!(version) if version
75
98
 
76
- version = log_data.find_by_time(ts).version
99
+ time ||= ts
100
+ time = parse_time(time)
101
+
102
+ return self if log_data.current_ts?(time)
103
+ return false unless log_data.exists_ts?(time)
104
+
105
+ version = log_data.find_by_time(time).version
77
106
 
78
107
  apply_diff(version, log_data.changes_to(version: version))
79
108
  end
@@ -99,11 +128,17 @@ module Logidze
99
128
  #
100
129
  # @example
101
130
  #
102
- # post.diff_from(2.days.ago)
131
+ # post.diff_from(time: 2.days.ago) # or post.diff_from(version: 2)
103
132
  # #=> { "id" => 1, "changes" => { "title" => { "old" => "Hello!", "new" => "World" } } }
104
- def diff_from(ts)
105
- ts = parse_time(ts)
106
- { "id" => id, "changes" => log_data.diff_from(time: ts) }
133
+ def diff_from(ts = nil, version: nil, time: nil)
134
+ Deprecations.show_ts_deprecation_for("#diff_from") if ts
135
+ time ||= ts
136
+ time = parse_time(time) if time
137
+ changes = log_data.diff_from(time: time, version: version).tap do |v|
138
+ deserialize_changes!(v)
139
+ end
140
+
141
+ { "id" => id, "changes" => changes }
107
142
  end
108
143
 
109
144
  # Restore record to the previous version.
@@ -135,6 +170,7 @@ module Logidze
135
170
  end
136
171
  end
137
172
 
173
+ # rubocop: disable Metrics/MethodLength
138
174
  def association(name)
139
175
  association = super
140
176
 
@@ -157,15 +193,40 @@ module Logidze
157
193
 
158
194
  association
159
195
  end
196
+ # rubocop: enable Metrics/MethodLength
160
197
 
161
198
  protected
162
199
 
163
200
  def apply_diff(version, diff)
164
- diff.each { |k, v| send("#{k}=", v) }
201
+ diff.each do |k, v|
202
+ apply_column_diff(k, v)
203
+ end
204
+
165
205
  log_data.version = version
166
206
  self
167
207
  end
168
208
 
209
+ def apply_column_diff(column, value)
210
+ write_attribute column, deserialize_value(column, value)
211
+ end
212
+
213
+ if Rails::VERSION::MAJOR < 5
214
+ def deserialize_value(column, value)
215
+ @attributes[column].type.type_cast_from_database(value)
216
+ end
217
+ else
218
+ def deserialize_value(column, value)
219
+ @attributes[column].type.deserialize(value)
220
+ end
221
+ end
222
+
223
+ def deserialize_changes!(diff)
224
+ diff.each do |k, v|
225
+ v["old"] = deserialize_value(k, v["old"])
226
+ v["new"] = deserialize_value(k, v["new"])
227
+ end
228
+ end
229
+
169
230
  def logidze_past?
170
231
  return false unless @logidze_requested_ts
171
232
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Logidze
3
- VERSION = "0.5.3"
3
+ VERSION = "0.6.0"
4
4
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- module Logidze
2
+ module Logidze # :nodoc: all
3
3
  module VersionedAssociation
4
+ # rubocop: disable Metrics/MethodLength, Metrics/AbcSize
4
5
  def load_target
5
6
  target = super
6
7
 
@@ -10,10 +11,10 @@ module Logidze
10
11
 
11
12
  if target.is_a? Array
12
13
  target.map! do |object|
13
- object.at(time)
14
+ object.at(time: time)
14
15
  end.compact!
15
16
  else
16
- target.at!(time)
17
+ target.at!(time: time)
17
18
  end
18
19
 
19
20
  target
@@ -26,9 +27,7 @@ module Logidze
26
27
  def logidze_stale?
27
28
  return false if !loaded? || inversed
28
29
 
29
- unless target.is_a?(Array)
30
- return owner.logidze_requested_ts != target.logidze_requested_ts
31
- end
30
+ return owner.logidze_requested_ts != target.logidze_requested_ts unless target.is_a?(Array)
32
31
 
33
32
  return false if target.empty?
34
33
 
data/logidze.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'logidze/version'
@@ -19,13 +19,14 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_dependency "rails", ">= 4.2"
21
21
 
22
- spec.add_development_dependency "pg", "~>0.18"
22
+ spec.add_development_dependency "ammeter", "~> 1.1.3"
23
23
  spec.add_development_dependency "bundler", "~> 1"
24
+ spec.add_development_dependency "database_cleaner", "~> 1.5"
25
+ spec.add_development_dependency "pg", "~>0.18"
26
+ spec.add_development_dependency "pry-byebug"
24
27
  spec.add_development_dependency "rake", ">= 10.0"
25
28
  spec.add_development_dependency "rspec-rails", ">= 3.4"
26
- spec.add_development_dependency "database_cleaner", "~> 1.5"
29
+ spec.add_development_dependency "rubocop", "~> 0.52"
27
30
  spec.add_development_dependency "simplecov", ">= 0.3.8"
28
- spec.add_development_dependency "ammeter", "~> 1.1.3"
29
- spec.add_development_dependency "pry-byebug"
30
31
  spec.add_development_dependency "timecop", "~> 0.8"
31
32
  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.5.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-22 00:00:00.000000000 Z
11
+ date: 2017-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.2'
27
27
  - !ruby/object:Gem::Dependency
28
- name: pg
28
+ name: ammeter
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.18'
33
+ version: 1.1.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.18'
40
+ version: 1.1.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,89 +53,103 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: database_cleaner
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '1.5'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '1.5'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec-rails
70
+ name: pg
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.18'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.18'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
74
88
  - !ruby/object:Gem::Version
75
- version: '3.4'
89
+ version: '0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
- version: '3.4'
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: database_cleaner
98
+ name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - "~>"
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
- version: '1.5'
103
+ version: '10.0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - "~>"
108
+ - - ">="
95
109
  - !ruby/object:Gem::Version
96
- version: '1.5'
110
+ version: '10.0'
97
111
  - !ruby/object:Gem::Dependency
98
- name: simplecov
112
+ name: rspec-rails
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - ">="
102
116
  - !ruby/object:Gem::Version
103
- version: 0.3.8
117
+ version: '3.4'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
- version: 0.3.8
124
+ version: '3.4'
111
125
  - !ruby/object:Gem::Dependency
112
- name: ammeter
126
+ name: rubocop
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - "~>"
116
130
  - !ruby/object:Gem::Version
117
- version: 1.1.3
131
+ version: '0.52'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
136
  - - "~>"
123
137
  - !ruby/object:Gem::Version
124
- version: 1.1.3
138
+ version: '0.52'
125
139
  - !ruby/object:Gem::Dependency
126
- name: pry-byebug
140
+ name: simplecov
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - ">="
130
144
  - !ruby/object:Gem::Version
131
- version: '0'
145
+ version: 0.3.8
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - ">="
137
151
  - !ruby/object:Gem::Version
138
- version: '0'
152
+ version: 0.3.8
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: timecop
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -226,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
240
  version: '0'
227
241
  requirements: []
228
242
  rubyforge_project:
229
- rubygems_version: 2.6.11
243
+ rubygems_version: 2.6.13
230
244
  signing_key:
231
245
  specification_version: 4
232
246
  summary: PostgreSQL JSON-based auditing