logidze 0.5.3 → 0.6.0

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: 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