logidze 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +13 -2
- data/CHANGELOG.md +11 -0
- data/README.md +32 -1
- data/lib/generators/logidze/install/templates/migration.rb.erb +35 -14
- data/lib/generators/logidze/model/model_generator.rb +33 -13
- data/lib/generators/logidze/model/templates/migration.rb.erb +1 -1
- data/lib/logidze/model.rb +56 -6
- data/lib/logidze/version.rb +1 -1
- data/lib/logidze/versioned_association.rb +52 -0
- data/lib/logidze.rb +11 -0
- data/logidze.gemspec +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8e3b2e4793fe16e96a40e2059df0b137be3a6b0
|
4
|
+
data.tar.gz: 96bdab4a164cdb0180d6b91b602b1d5831245512
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b5eccd3de9563162195ca6e8350ed3136a696085485bdd95a806e6eef449b2d76b9690b4aea6558773d39df321be5bbb8998b97f5461907763643bb7f8800e2
|
7
|
+
data.tar.gz: 1b1389f59b82cb3fc637151e3c8561cea387a7d83a58dbf93805d619916b34ca0a682e0be54d88bb934ff4caa1697d2ed2986167837234fdf36f8d6513844a4b
|
data/.rubocop.yml
CHANGED
@@ -23,7 +23,7 @@ Style/Documentation:
|
|
23
23
|
Exclude:
|
24
24
|
- 'spec/**/*.rb'
|
25
25
|
|
26
|
-
Style/StringLiterals:
|
26
|
+
Style/StringLiterals:
|
27
27
|
Enabled: false
|
28
28
|
|
29
29
|
Style/SpaceInsideStringInterpolation:
|
@@ -49,4 +49,15 @@ Rails/Date:
|
|
49
49
|
Enabled: false
|
50
50
|
|
51
51
|
Rails/TimeZone:
|
52
|
-
Enabled: false
|
52
|
+
Enabled: false
|
53
|
+
|
54
|
+
Style/NumericLiteralPrefix:
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
Lint/HandleExceptions:
|
58
|
+
Enabled: true
|
59
|
+
Exclude:
|
60
|
+
- 'spec/**/*.rb'
|
61
|
+
|
62
|
+
Style/DotPosition:
|
63
|
+
EnforcedStyle: leading
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## 0.5.0 (2017-03-28)
|
4
|
+
|
5
|
+
- Add an option to preserve future versions. ([@akxcv][])
|
6
|
+
|
7
|
+
- Add `--timestamp_column` option to model migration generator. ([@akxcv][])
|
8
|
+
|
9
|
+
- Default version timestamp to timestamp column. ([@akxcv][])
|
10
|
+
|
11
|
+
- Associations versioning. ([@charlie-wasp][])
|
12
|
+
|
3
13
|
## 0.4.1 (2017-02-06)
|
4
14
|
|
5
15
|
- Add `--path` option to model migration generator. ([@palkan][])
|
@@ -36,3 +46,4 @@
|
|
36
46
|
|
37
47
|
[@palkan]: https://github.com/palkan
|
38
48
|
[@charlie-wasp]: https://github.com/charlie-wasp
|
49
|
+
[@akxcv]: https://github.com/akxcv
|
data/README.md
CHANGED
@@ -75,6 +75,20 @@ By default, Logidze tries to infer the path to the model file from the model nam
|
|
75
75
|
rails generate logidze:model Post --path "app/models/custom/post.rb"
|
76
76
|
```
|
77
77
|
|
78
|
+
By default, Logidze tries to get a timestamp for a version from record's `updated_at` field whenever appropriate. If
|
79
|
+
your model does not have that column, Logidze will gracefully fall back to `statement_timestamp()`.
|
80
|
+
To change the column name or disable this feature completely, you can use the `timestamp_column` option:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# will try to get the timestamp value from `time` column
|
84
|
+
rails generate logidze:model Post --timestamp_column time
|
85
|
+
# will always set version timestamp to `statement_timestamp()`
|
86
|
+
rails generate logidze:model Post --timestamp_column nil # "null" and "false" will also work
|
87
|
+
```
|
88
|
+
|
89
|
+
Logidze also supports associations versioning. It is experimental feature, and disabled by default. You can learn more
|
90
|
+
in the [wiki](https://github.com/palkan/logidze/wiki/Associations-versioning).
|
91
|
+
|
78
92
|
## Troubleshooting
|
79
93
|
|
80
94
|
The most common problem is `"permission denied to set parameter "logidze.xxx"` caused by `ALTER DATABASE ...` query.
|
@@ -157,7 +171,24 @@ post.redo!
|
|
157
171
|
post.switch_to!(2)
|
158
172
|
```
|
159
173
|
|
160
|
-
|
174
|
+
Normally, if you update record after `#undo!` or `#switch_to!` you lose all "future" versions and `#redo!` is no
|
175
|
+
longer possible. However, you can provide an `append: true` option to `#undo!` or `#switch_to!`, which will
|
176
|
+
create a new version with old data. Caveat: when switching to a newer version, `append` will have no effect.
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
post = Post.create!(title: 'first post') # v1
|
180
|
+
post.update!(title: 'new title') # v2
|
181
|
+
post.undo!(append: true) # v3 (with same attributes as v1)
|
182
|
+
```
|
183
|
+
|
184
|
+
Note that `redo!` will not work after `undo!(append: true)` because the latter will create a new version
|
185
|
+
instead of rolling back to an old one.
|
186
|
+
Alternatively, you can configure Logidze to always default to `append: true`.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
Logidze.append_on_undo = true
|
190
|
+
```
|
191
|
+
|
161
192
|
|
162
193
|
## Track responsibility (aka _whodunnit_)
|
163
194
|
|
@@ -19,17 +19,19 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
19
19
|
execute <<-SQL
|
20
20
|
DROP FUNCTION IF EXISTS logidze_version(bigint, jsonb);
|
21
21
|
DROP FUNCTION IF EXISTS logidze_snapshot(jsonb);
|
22
|
+
DROP FUNCTION IF EXISTS logidze_version(bigint, jsonb, text[]);
|
23
|
+
DROP FUNCTION IF EXISTS logidze_snapshot(jsonb, text[]);
|
22
24
|
SQL
|
23
25
|
<% end %>
|
24
26
|
|
25
27
|
execute <<-SQL
|
26
|
-
CREATE OR REPLACE FUNCTION logidze_version(v bigint, data jsonb, blacklist text[] DEFAULT '{}') RETURNS jsonb AS $body$
|
28
|
+
CREATE OR REPLACE FUNCTION logidze_version(v bigint, data jsonb, ts timestamp with time zone, blacklist text[] DEFAULT '{}') RETURNS jsonb AS $body$
|
27
29
|
DECLARE
|
28
30
|
buf jsonb;
|
29
31
|
BEGIN
|
30
32
|
buf := jsonb_build_object(
|
31
33
|
'ts',
|
32
|
-
(extract(epoch from
|
34
|
+
(extract(epoch from ts) * 1000)::bigint,
|
33
35
|
'v',
|
34
36
|
v,
|
35
37
|
'c',
|
@@ -43,12 +45,19 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
43
45
|
$body$
|
44
46
|
LANGUAGE plpgsql;
|
45
47
|
|
46
|
-
CREATE OR REPLACE FUNCTION logidze_snapshot(item jsonb, blacklist text[] DEFAULT '{}') RETURNS jsonb AS $body$
|
48
|
+
CREATE OR REPLACE FUNCTION logidze_snapshot(item jsonb, ts_column text, blacklist text[] DEFAULT '{}') RETURNS jsonb AS $body$
|
49
|
+
DECLARE
|
50
|
+
ts timestamp with time zone;
|
47
51
|
BEGIN
|
52
|
+
IF ts_column IS NULL THEN
|
53
|
+
ts := statement_timestamp();
|
54
|
+
ELSE
|
55
|
+
ts := coalesce((item->>ts_column)::timestamp with time zone, statement_timestamp());
|
56
|
+
END IF;
|
48
57
|
return json_build_object(
|
49
58
|
'v', 1,
|
50
59
|
'h', jsonb_build_array(
|
51
|
-
logidze_version(1, item, blacklist)
|
60
|
+
logidze_version(1, item, ts, blacklist)
|
52
61
|
)
|
53
62
|
);
|
54
63
|
END;
|
@@ -62,7 +71,7 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
62
71
|
BEGIN
|
63
72
|
res := obj;
|
64
73
|
FOREACH key IN ARRAY keys
|
65
|
-
LOOP
|
74
|
+
LOOP
|
66
75
|
res := res - key;
|
67
76
|
END LOOP;
|
68
77
|
RETURN res;
|
@@ -93,7 +102,7 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
93
102
|
jsonb_set(
|
94
103
|
log_data->'h',
|
95
104
|
'{1}',
|
96
|
-
merged
|
105
|
+
merged
|
97
106
|
) - 0
|
98
107
|
);
|
99
108
|
END;
|
@@ -111,23 +120,35 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
111
120
|
iterator integer;
|
112
121
|
item record;
|
113
122
|
columns_blacklist text[];
|
123
|
+
ts timestamp with time zone;
|
124
|
+
ts_column text;
|
114
125
|
BEGIN
|
115
|
-
|
126
|
+
ts_column := NULLIF(TG_ARGV[1], 'null');
|
127
|
+
columns_blacklist := TG_ARGV[2];
|
116
128
|
|
117
129
|
IF TG_OP = 'INSERT' THEN
|
118
130
|
|
119
|
-
NEW.log_data := logidze_snapshot(to_jsonb(NEW.*), columns_blacklist);
|
120
|
-
|
131
|
+
NEW.log_data := logidze_snapshot(to_jsonb(NEW.*), ts_column, columns_blacklist);
|
132
|
+
|
121
133
|
ELSIF TG_OP = 'UPDATE' THEN
|
122
|
-
|
134
|
+
|
123
135
|
IF OLD.log_data is NULL OR OLD.log_data = '{}'::jsonb THEN
|
124
|
-
NEW.log_data := logidze_snapshot(to_jsonb(NEW.*), columns_blacklist);
|
136
|
+
NEW.log_data := logidze_snapshot(to_jsonb(NEW.*), ts_column, columns_blacklist);
|
125
137
|
RETURN NEW;
|
126
138
|
END IF;
|
127
139
|
|
128
140
|
history_limit := NULLIF(TG_ARGV[0], 'null');
|
129
141
|
current_version := (NEW.log_data->>'v')::int;
|
130
142
|
|
143
|
+
IF ts_column IS NULL THEN
|
144
|
+
ts := statement_timestamp();
|
145
|
+
ELSE
|
146
|
+
ts := (to_jsonb(NEW.*)->>ts_column)::timestamp with time zone;
|
147
|
+
IF ts IS NULL OR ts = (to_jsonb(OLD.*)->>ts_column)::timestamp with time zone THEN
|
148
|
+
ts := statement_timestamp();
|
149
|
+
END IF;
|
150
|
+
END IF;
|
151
|
+
|
131
152
|
IF NEW = OLD THEN
|
132
153
|
RETURN NEW;
|
133
154
|
END IF;
|
@@ -158,7 +179,7 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
158
179
|
NEW.log_data := jsonb_set(
|
159
180
|
NEW.log_data,
|
160
181
|
ARRAY['h', size::text],
|
161
|
-
logidze_version(new_v, changes, columns_blacklist),
|
182
|
+
logidze_version(new_v, changes, ts, columns_blacklist),
|
162
183
|
true
|
163
184
|
);
|
164
185
|
|
@@ -183,9 +204,9 @@ class <%= @migration_class_name %> < ActiveRecord::Migration
|
|
183
204
|
def down
|
184
205
|
<% unless update? %>
|
185
206
|
execute <<-SQL
|
186
|
-
DROP FUNCTION logidze_version(bigint, jsonb, text[]) CASCADE;
|
207
|
+
DROP FUNCTION logidze_version(bigint, jsonb, timestamp with time zone, text[]) CASCADE;
|
187
208
|
DROP FUNCTION logidze_compact_history(jsonb) CASCADE;
|
188
|
-
DROP FUNCTION logidze_snapshot(jsonb, text[]) CASCADE;
|
209
|
+
DROP FUNCTION logidze_snapshot(jsonb, text, text[]) CASCADE;
|
189
210
|
DROP FUNCTION logidze_logger() CASCADE;
|
190
211
|
SQL
|
191
212
|
<% end %>
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# rubocop:disable Metrics/BlockLength
|
1
2
|
# frozen_string_literal: true
|
2
3
|
require "rails/generators"
|
3
4
|
require "rails/generators/active_record/migration/migration_generator"
|
@@ -20,6 +21,9 @@ module Logidze
|
|
20
21
|
class_option :blacklist, type: :array, optional: true
|
21
22
|
class_option :whitelist, type: :array, optional: true
|
22
23
|
|
24
|
+
class_option :timestamp_column, type: :string, optional: true,
|
25
|
+
desc: "Specify timestamp column"
|
26
|
+
|
23
27
|
def generate_migration
|
24
28
|
if options[:blacklist] && options[:whitelist]
|
25
29
|
$stderr.puts "Use only one: --whitelist or --blacklist"
|
@@ -62,30 +66,46 @@ module Logidze
|
|
62
66
|
class_name.constantize.column_names - options[:whitelist]
|
63
67
|
end
|
64
68
|
|
65
|
-
array
|
69
|
+
format_pgsql_array(array)
|
70
|
+
end
|
71
|
+
|
72
|
+
def timestamp_column
|
73
|
+
value = options[:timestamp_column] || 'updated_at'
|
74
|
+
return if %w(nil null false).include?(value)
|
75
|
+
escape_pgsql_string(value)
|
66
76
|
end
|
67
77
|
|
68
78
|
def logidze_logger_parameters
|
69
|
-
|
70
|
-
''
|
71
|
-
elsif !limit.nil? && columns_blacklist.empty?
|
72
|
-
limit
|
73
|
-
elsif !limit.nil? && !columns_blacklist.empty?
|
74
|
-
"#{limit}, #{format_pgsql_array(columns_blacklist)}"
|
75
|
-
elsif limit.nil? && !columns_blacklist.empty?
|
76
|
-
"null, #{format_pgsql_array(columns_blacklist)}"
|
77
|
-
end
|
79
|
+
format_pgsql_args(limit, timestamp_column, columns_blacklist)
|
78
80
|
end
|
79
81
|
|
80
82
|
def logidze_snapshot_parameters
|
81
|
-
|
82
|
-
|
83
|
-
"to_jsonb(t), #{format_pgsql_array(columns_blacklist)}"
|
83
|
+
format_pgsql_args('to_jsonb(t)', timestamp_column, columns_blacklist)
|
84
84
|
end
|
85
85
|
|
86
86
|
def format_pgsql_array(ruby_array)
|
87
|
+
return if ruby_array.blank?
|
87
88
|
"'{" + ruby_array.join(', ') + "}'"
|
88
89
|
end
|
90
|
+
|
91
|
+
def escape_pgsql_string(string)
|
92
|
+
return if string.blank?
|
93
|
+
"'#{string}'"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Convenience method for formatting pg arguments.
|
97
|
+
# Some examples:
|
98
|
+
# format_pgsql_args('a', 'b', nil) #=> "a, b"
|
99
|
+
# format_pgsql_args(nil, '', 'c') #=> "null, null, c"
|
100
|
+
# format_pgsql_args('a', '', []) #=> "a"
|
101
|
+
def format_pgsql_args(*values)
|
102
|
+
args = []
|
103
|
+
values.reverse_each do |value|
|
104
|
+
formatted_value = value.presence || (args.any? && 'null')
|
105
|
+
args << formatted_value if formatted_value
|
106
|
+
end
|
107
|
+
args.compact.reverse.join(', ')
|
108
|
+
end
|
89
109
|
end
|
90
110
|
|
91
111
|
private
|
data/lib/logidze/model.rb
CHANGED
@@ -33,23 +33,38 @@ module Logidze
|
|
33
33
|
def without_logging(&block)
|
34
34
|
Logidze.without_logging(&block)
|
35
35
|
end
|
36
|
+
|
37
|
+
def has_logidze?
|
38
|
+
true
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
# Use this to convert Ruby time to milliseconds
|
39
43
|
TIME_FACTOR = 1_000
|
40
44
|
|
45
|
+
attr_accessor :logidze_requested_ts
|
46
|
+
|
41
47
|
# Return a dirty copy of record at specified time
|
42
48
|
# If time is less then the first version, then return nil.
|
43
49
|
# If time is greater then the last version, then return self.
|
44
50
|
def at(ts)
|
45
51
|
ts = parse_time(ts)
|
52
|
+
|
46
53
|
return nil unless log_data.exists_ts?(ts)
|
47
|
-
|
54
|
+
|
55
|
+
if log_data.current_ts?(ts)
|
56
|
+
self.logidze_requested_ts = ts
|
57
|
+
return self
|
58
|
+
end
|
48
59
|
|
49
60
|
version = log_data.find_by_time(ts).version
|
50
61
|
|
51
62
|
object_at = dup
|
52
63
|
object_at.apply_diff(version, log_data.changes_to(version: version))
|
64
|
+
object_at.id = id
|
65
|
+
object_at.logidze_requested_ts = ts
|
66
|
+
|
67
|
+
object_at
|
53
68
|
end
|
54
69
|
|
55
70
|
# Revert record to the version at specified time (without saving to DB)
|
@@ -93,10 +108,10 @@ module Logidze
|
|
93
108
|
|
94
109
|
# Restore record to the previous version.
|
95
110
|
# Return false if no previous version found, otherwise return updated record.
|
96
|
-
def undo!
|
111
|
+
def undo!(append: Logidze.append_on_undo)
|
97
112
|
version = log_data.previous_version
|
98
113
|
return false if version.nil?
|
99
|
-
switch_to!(version.version)
|
114
|
+
switch_to!(version.version, append: append)
|
100
115
|
end
|
101
116
|
|
102
117
|
# Restore record to the _future_ version (if `undo!` was applied)
|
@@ -109,9 +124,38 @@ module Logidze
|
|
109
124
|
|
110
125
|
# Restore record to the specified version.
|
111
126
|
# Return false if version is unknown.
|
112
|
-
def switch_to!(version)
|
113
|
-
return false unless at_version
|
114
|
-
|
127
|
+
def switch_to!(version, append: Logidze.append_on_undo)
|
128
|
+
return false unless at_version(version)
|
129
|
+
|
130
|
+
if append && version < log_version
|
131
|
+
update!(log_data.changes_to(version: version))
|
132
|
+
else
|
133
|
+
at_version!(version)
|
134
|
+
self.class.without_logging { save! }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def association(name)
|
139
|
+
association = super
|
140
|
+
|
141
|
+
return association unless Logidze.associations_versioning
|
142
|
+
|
143
|
+
should_appply_logidze =
|
144
|
+
logidze_past? &&
|
145
|
+
association.klass.respond_to?(:has_logidze?) &&
|
146
|
+
!association.singleton_class.include?(Logidze::VersionedAssociation)
|
147
|
+
|
148
|
+
return association unless should_appply_logidze
|
149
|
+
|
150
|
+
association.singleton_class.prepend Logidze::VersionedAssociation
|
151
|
+
|
152
|
+
if association.is_a? ActiveRecord::Associations::CollectionAssociation
|
153
|
+
association.singleton_class.prepend(
|
154
|
+
Logidze::VersionedAssociation::CollectionAssociation
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
association
|
115
159
|
end
|
116
160
|
|
117
161
|
protected
|
@@ -122,6 +166,12 @@ module Logidze
|
|
122
166
|
self
|
123
167
|
end
|
124
168
|
|
169
|
+
def logidze_past?
|
170
|
+
return false unless @logidze_requested_ts
|
171
|
+
|
172
|
+
@logidze_requested_ts < Time.now.to_i * TIME_FACTOR
|
173
|
+
end
|
174
|
+
|
125
175
|
def parse_time(ts)
|
126
176
|
case ts
|
127
177
|
when Numeric
|
data/lib/logidze/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Logidze
|
3
|
+
module VersionedAssociation
|
4
|
+
def load_target
|
5
|
+
target = super
|
6
|
+
|
7
|
+
return target if inversed
|
8
|
+
|
9
|
+
time = owner.logidze_requested_ts
|
10
|
+
|
11
|
+
if target.is_a? Array
|
12
|
+
target.map! do |object|
|
13
|
+
object.at(time)
|
14
|
+
end.compact!
|
15
|
+
else
|
16
|
+
target.at!(time)
|
17
|
+
end
|
18
|
+
|
19
|
+
target
|
20
|
+
end
|
21
|
+
|
22
|
+
def stale_target?
|
23
|
+
logidze_stale? || super
|
24
|
+
end
|
25
|
+
|
26
|
+
def logidze_stale?
|
27
|
+
return false if !loaded? || inversed
|
28
|
+
|
29
|
+
unless target.is_a?(Array)
|
30
|
+
return owner.logidze_requested_ts != target.logidze_requested_ts
|
31
|
+
end
|
32
|
+
|
33
|
+
return false if target.empty?
|
34
|
+
|
35
|
+
target.any? do |object|
|
36
|
+
owner.logidze_requested_ts != object.logidze_requested_ts
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module CollectionAssociation
|
41
|
+
def ids_reader
|
42
|
+
reload unless loaded?
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def empty?
|
47
|
+
reload unless loaded?
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/logidze.rb
CHANGED
@@ -6,6 +6,7 @@ require "logidze/version"
|
|
6
6
|
module Logidze
|
7
7
|
require 'logidze/history'
|
8
8
|
require 'logidze/model'
|
9
|
+
require 'logidze/versioned_association'
|
9
10
|
require 'logidze/has_logidze'
|
10
11
|
require 'logidze/responsible'
|
11
12
|
|
@@ -13,6 +14,16 @@ module Logidze
|
|
13
14
|
|
14
15
|
require 'logidze/engine' if defined?(Rails)
|
15
16
|
|
17
|
+
class << self
|
18
|
+
# Determines if Logidze should append a version to the log after updating an old version.
|
19
|
+
attr_accessor :append_on_undo
|
20
|
+
attr_writer :associations_versioning
|
21
|
+
|
22
|
+
def associations_versioning
|
23
|
+
@associations_versioning || false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
16
27
|
# Temporary disable DB triggers.
|
17
28
|
#
|
18
29
|
# @example
|
data/logidze.gemspec
CHANGED
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.
|
4
|
+
version: 0.5.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-
|
11
|
+
date: 2017-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: timecop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.8'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.8'
|
139
153
|
description: PostgreSQL JSON-based auditing
|
140
154
|
email:
|
141
155
|
- dementiev.vm@gmail.com
|
@@ -189,6 +203,7 @@ files:
|
|
189
203
|
- lib/logidze/model.rb
|
190
204
|
- lib/logidze/responsible.rb
|
191
205
|
- lib/logidze/version.rb
|
206
|
+
- lib/logidze/versioned_association.rb
|
192
207
|
- logidze.gemspec
|
193
208
|
homepage: http://github.com/palkan/logidze
|
194
209
|
licenses:
|