effective_logging 2.1.2 → 3.0.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 +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +1 -3
- data/app/datatables/effective_log_changes_datatable.rb +43 -0
- data/app/datatables/effective_logs_datatable.rb +5 -15
- data/app/models/concerns/acts_as_loggable.rb +14 -26
- data/app/models/effective/log.rb +6 -5
- data/app/views/effective/logs/_log.html.haml +1 -1
- data/db/migrate/01_create_effective_logging.rb.erb +4 -1
- data/lib/effective_logging/active_record_logger.rb +44 -134
- data/lib/effective_logging/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20e9e57d5a67995068422a609568b3124e6bab4b
|
4
|
+
data.tar.gz: be6fdf6286b4b661881e13e529b8f7ce220cdccf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb7025f50e12b1fca55f87a66ae177b923a0d06800d9b3fa1fc0979e08b97a48976e31c341a2f522d521c49d487ccdf652be893a7c98c0644eefe5af421f9269
|
7
|
+
data.tar.gz: 744819fb3d4dd1d27c02064c5cd09ce504c650a3cb91d96c1aed298d5810b3bcabc79ce24abac6e3b7d517672cd3da89d9e850c8d63f9dad5649b03114e78ccf
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -233,9 +233,7 @@ class Post < ActiveRecord::Base
|
|
233
233
|
end
|
234
234
|
```
|
235
235
|
|
236
|
-
There is some initial support for passing `only`, `except`,
|
237
|
-
|
238
|
-
Define your model with `log_changes additionally: [:method1, :method2]` to also _always_ log the value of that method. Even if it's unchanged.
|
236
|
+
There is some initial support for passing `only`, and `except`, to the mixin to customize what attributes are saved.
|
239
237
|
|
240
238
|
Apply your own formatting to the logged title of each attribute by creating an instance method on the resource:
|
241
239
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class EffectiveLogChangesDatatable < Effective::Datatable
|
2
|
+
datatable do
|
3
|
+
order :updated_at
|
4
|
+
|
5
|
+
col :updated_at, label: 'Date'
|
6
|
+
col :id, visible: false
|
7
|
+
|
8
|
+
col :user, sort: false
|
9
|
+
|
10
|
+
col :associated_type, visible: false
|
11
|
+
col :associated_id, visible: false
|
12
|
+
col :associated_to_s, visible: false
|
13
|
+
|
14
|
+
col :message, sort: false do |log|
|
15
|
+
message = log.message.gsub("\n", '<br>')
|
16
|
+
|
17
|
+
if log.associated_id == attributes[:changes_to_id] && log.associated_type == attributes[:changes_to_type]
|
18
|
+
message
|
19
|
+
else
|
20
|
+
"#{log.associated_type} #{log.associated_to_s} - #{message}"
|
21
|
+
end
|
22
|
+
|
23
|
+
end.search do |collection, term, column, sql_column|
|
24
|
+
collection.where("associated_type #{resource.ilike} ? OR associated_to_s #{resource.ilike} ? OR message #{resource.ilike} ?", "%#{term}%", "%#{term}%", "%#{term}%")
|
25
|
+
end
|
26
|
+
|
27
|
+
col :details, visible: false, sort: false do |log|
|
28
|
+
tableize_hash(log.details)
|
29
|
+
end
|
30
|
+
|
31
|
+
unless attributes[:actions] == false
|
32
|
+
actions_col partial: 'admin/logs/actions', partial_as: :log
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# A nil attributes[:log_id] means give me all the top level log entries
|
37
|
+
# If we set a log_id then it's for sub logs
|
38
|
+
collection do
|
39
|
+
Effective::Log.logged_changes.deep
|
40
|
+
.where(changes_to_type: attributes[:changes_to_type], changes_to_id: attributes[:changes_to_id])
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -17,18 +17,12 @@ class EffectiveLogsDatatable < Effective::Datatable
|
|
17
17
|
col :status, search: { collection: EffectiveLogging.statuses }
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
col :associated_to_s, search: { as: :string }, label: 'Associated'
|
24
|
-
end
|
20
|
+
col :associated_type, search: { as: :string }
|
21
|
+
col :associated_id, search: { as: :integer }, visible: false, label: 'Associated Id'
|
22
|
+
col :associated_to_s, search: { as: :string }, label: 'Associated'
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
log.message.starts_with?("\t") ? log.message.gsub("\t", " ") : log.message
|
29
|
-
end
|
30
|
-
else
|
31
|
-
col :message
|
24
|
+
col :message do |log|
|
25
|
+
log.message.gsub("\n", '<br>')
|
32
26
|
end
|
33
27
|
|
34
28
|
col :logs_count, visible: false
|
@@ -47,10 +41,6 @@ class EffectiveLogsDatatable < Effective::Datatable
|
|
47
41
|
collection do
|
48
42
|
scope = Effective::Log.deep.where(parent_id: attributes[:log_id])
|
49
43
|
|
50
|
-
if attributes[:log_changes]
|
51
|
-
scope = scope.where(status: EffectiveLogging.log_changes_status)
|
52
|
-
end
|
53
|
-
|
54
44
|
if attributes[:for]
|
55
45
|
user_ids = Array(attributes[:for])
|
56
46
|
scope = scope.where('user_id IN (?) OR (associated_id IN (?) AND associated_type = ?)', user_ids, user_ids, 'User')
|
@@ -9,7 +9,7 @@ module ActsAsLoggable
|
|
9
9
|
raise ArgumentError.new('invalid arguments passed to (effective_logging) log_changes. Example usage: log_changes except: [:created_at]')
|
10
10
|
end
|
11
11
|
|
12
|
-
if (unknown = (@acts_as_loggable_options.keys - [:
|
12
|
+
if (unknown = (@acts_as_loggable_options.keys - [:to, :prefix, :only, :except])).present?
|
13
13
|
raise ArgumentError.new("unknown keyword: #{unknown.join(', ')}")
|
14
14
|
end
|
15
15
|
|
@@ -18,64 +18,52 @@ module ActsAsLoggable
|
|
18
18
|
end
|
19
19
|
|
20
20
|
included do
|
21
|
-
has_many :logged_changes, -> { order(:id).where(status: EffectiveLogging.log_changes_status) }, as: :
|
21
|
+
has_many :logged_changes, -> { order(:id).where(status: EffectiveLogging.log_changes_status) }, as: :changes_to, class_name: 'Effective::Log'
|
22
22
|
|
23
23
|
log_changes_options = {
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
include_nested: @acts_as_loggable_options.fetch(:include_nested, true)
|
24
|
+
to: @acts_as_loggable_options[:to],
|
25
|
+
prefix: @acts_as_loggable_options[:prefix],
|
26
|
+
only: Array(@acts_as_loggable_options[:only]),
|
27
|
+
except: Array(@acts_as_loggable_options[:except])
|
29
28
|
}
|
30
29
|
|
31
30
|
if name == 'User'
|
32
|
-
log_changes_options[:except] += %
|
31
|
+
log_changes_options[:except] += %i(sign_in_count current_sign_in_at current_sign_in_ip last_sign_in_at last_sign_in_ip encrypted_password remember_created_at reset_password_token invitation_sent_at invitation_created_at invitation_token)
|
33
32
|
end
|
34
33
|
|
35
34
|
self.send(:define_method, :log_changes_options) { log_changes_options }
|
36
35
|
|
37
36
|
after_create(unless: -> { EffectiveLogging.supressed? }) do
|
38
|
-
::EffectiveLogging::ActiveRecordLogger.new(self, log_changes_options).
|
37
|
+
::EffectiveLogging::ActiveRecordLogger.new(self, log_changes_options).created!
|
39
38
|
end
|
40
39
|
|
41
40
|
after_destroy(unless: -> { EffectiveLogging.supressed? }) do
|
42
|
-
::EffectiveLogging::ActiveRecordLogger.new(self, log_changes_options).
|
41
|
+
::EffectiveLogging::ActiveRecordLogger.new(self, log_changes_options).destroyed!
|
43
42
|
end
|
44
43
|
|
45
44
|
after_update(unless: -> { EffectiveLogging.supressed? }) do
|
46
|
-
::EffectiveLogging::ActiveRecordLogger.new(self, log_changes_options).
|
45
|
+
::EffectiveLogging::ActiveRecordLogger.new(self, log_changes_options).updated!
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
49
|
module ClassMethods
|
50
|
+
def acts_as_loggable?; true; end
|
51
51
|
end
|
52
52
|
|
53
53
|
# Regular instance methods
|
54
54
|
|
55
55
|
# Format the title of this attribute. Return nil to use the default attribute.titleize
|
56
56
|
def log_changes_formatted_attribute(attribute)
|
57
|
-
if attribute == 'roles_mask' && defined?(EffectiveRoles) && respond_to?(:roles)
|
58
|
-
'Roles'
|
59
|
-
end
|
57
|
+
'Roles' if attribute == 'roles_mask' && defined?(EffectiveRoles) && respond_to?(:roles)
|
60
58
|
end
|
61
59
|
|
62
60
|
# Format the value of this attribute. Return nil to use the default to_s
|
63
61
|
def log_changes_formatted_value(attribute, value)
|
64
|
-
if attribute == 'roles_mask' && defined?(EffectiveRoles) && respond_to?(:roles)
|
65
|
-
EffectiveRoles.roles_for(value)
|
66
|
-
end
|
62
|
+
EffectiveRoles.roles_for(value) if attribute == 'roles_mask' && defined?(EffectiveRoles) && respond_to?(:roles)
|
67
63
|
end
|
68
64
|
|
69
65
|
def log_changes_datatable
|
70
|
-
|
71
|
-
|
72
|
-
@log_changes_datatable ||= (
|
73
|
-
EffectiveLogsDatatable.new(associated_id: id, associated_type: self.class.name, log_changes: true, status: false)
|
74
|
-
)
|
75
|
-
end
|
76
|
-
|
77
|
-
def refresh_datatables
|
78
|
-
@refresh_datatables ||= [:effective_logs]
|
66
|
+
EffectiveLogChangesDatatable.new(changes_to_id: id, changes_to_type: self.class.name) if persisted?
|
79
67
|
end
|
80
68
|
|
81
69
|
end
|
data/app/models/effective/log.rb
CHANGED
@@ -12,6 +12,8 @@ module Effective
|
|
12
12
|
has_many :logs, class_name: 'Effective::Log', foreign_key: :parent_id
|
13
13
|
|
14
14
|
belongs_to :user
|
15
|
+
|
16
|
+
belongs_to :changes_to, polymorphic: true # This is the log_changes to: option
|
15
17
|
belongs_to :associated, polymorphic: true
|
16
18
|
|
17
19
|
serialize :details, Hash
|
@@ -19,10 +21,13 @@ module Effective
|
|
19
21
|
# Attributes
|
20
22
|
# logs_count :integer # Rails Counter Cache
|
21
23
|
|
24
|
+
# changes_to_type :string
|
25
|
+
# changes_to_id :string
|
26
|
+
|
22
27
|
# associated_type :string
|
23
28
|
# associated_id :integer
|
24
29
|
# associated_to_s :string
|
25
|
-
# message :
|
30
|
+
# message :text
|
26
31
|
# details :text
|
27
32
|
# status :string
|
28
33
|
# timestamps
|
@@ -39,10 +44,6 @@ module Effective
|
|
39
44
|
"Log #{id}"
|
40
45
|
end
|
41
46
|
|
42
|
-
def message=(msg)
|
43
|
-
write_attribute(:message, msg.kind_of?(String) ? msg.to_s[0...255] : msg)
|
44
|
-
end
|
45
|
-
|
46
47
|
def log(message, status = EffectiveLogging.statuses.first, options = {})
|
47
48
|
EffectiveLogger.log(message, status, (options || {}).merge(parent: self))
|
48
49
|
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
- parents_of_log(log).each do |parent|
|
6
6
|
= link_to(log.message, request.fullpath.sub('/' + log.to_param, '/' + parent.to_param))
|
7
7
|
= ' > '
|
8
|
-
%p= log.message.html_safe
|
8
|
+
%p= log.message.to_s.gsub("\n", '<br>').html_safe
|
9
9
|
|
10
10
|
.col-md-4.text-right
|
11
11
|
- if log.prev_log
|
@@ -5,13 +5,16 @@ class CreateEffectiveLogging < ActiveRecord::Migration[4.2]
|
|
5
5
|
|
6
6
|
t.integer :user_id
|
7
7
|
|
8
|
+
t.string :changes_to_type
|
9
|
+
t.integer :changes_to_id
|
10
|
+
|
8
11
|
t.string :associated_type
|
9
12
|
t.integer :associated_id
|
10
13
|
t.string :associated_to_s
|
11
14
|
|
12
15
|
t.integer :logs_count
|
13
16
|
|
14
|
-
t.
|
17
|
+
t.text :message
|
15
18
|
t.text :details
|
16
19
|
|
17
20
|
t.string :status
|
@@ -1,179 +1,89 @@
|
|
1
1
|
module EffectiveLogging
|
2
2
|
class ActiveRecordLogger
|
3
|
-
attr_accessor :object, :resource, :
|
3
|
+
attr_accessor :object, :resource, :options
|
4
4
|
|
5
5
|
BLANK = "''"
|
6
|
+
BLACKLIST = [:updated_at, :created_at, :encrypted_password, :status_steps] # Don't log changes or attributes
|
6
7
|
|
7
|
-
def initialize(object,
|
8
|
-
raise ArgumentError.new('options must be a Hash') unless options.kind_of?(Hash)
|
9
|
-
|
8
|
+
def initialize(object, to: nil, prefix: nil, only: nil, except: nil)
|
10
9
|
@object = object
|
11
10
|
@resource = Effective::Resource.new(object)
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@include_nested = options.fetch(:include_nested, true)
|
17
|
-
@log_parents = options.fetch(:log_parents, true)
|
18
|
-
@options = options
|
19
|
-
|
20
|
-
raise ArgumentError.new('logger must respond to logged_changes') unless @logger.respond_to?(:logged_changes)
|
21
|
-
end
|
22
|
-
|
23
|
-
def execute!
|
24
|
-
@logged = false
|
25
|
-
|
26
|
-
if new_record?(object)
|
27
|
-
created!
|
28
|
-
elsif destroyed_record?(object)
|
29
|
-
destroyed!
|
30
|
-
else
|
31
|
-
updated!
|
12
|
+
# Validate changes_to value
|
13
|
+
if to.present? && !@resource.belong_tos.map(&:name).include?(to)
|
14
|
+
raise ArgumentError.new("unable to find existing belongs_to relationship matching #{to}. Expected a symbol matching a belongs_to.")
|
32
15
|
end
|
33
16
|
|
34
|
-
|
17
|
+
@options = { to: to, prefix: prefix, only: only, except: Array(except) + BLACKLIST }.compact
|
35
18
|
end
|
36
19
|
|
20
|
+
# Effective::Log.where(message: 'Deleted').where('details ILIKE ?', '%lab_test_id: 263%')
|
37
21
|
def destroyed!
|
38
|
-
log('Deleted',
|
22
|
+
log('Deleted', resource_attributes)
|
39
23
|
end
|
40
24
|
|
41
25
|
def created!
|
42
|
-
log('Created',
|
26
|
+
log('Created', resource_attributes)
|
43
27
|
end
|
44
28
|
|
45
29
|
def updated!
|
46
|
-
|
47
|
-
log_nested_resources!
|
48
|
-
|
49
|
-
(logged? && depth == 0) ? log('Updated', applicable(instance_attributes)) : true
|
50
|
-
end
|
51
|
-
|
52
|
-
def log_resource_changes!
|
53
|
-
applicable(resource.instance_changes).each do |attribute, (before, after)|
|
54
|
-
if object.respond_to?(:log_changes_formatted_value)
|
55
|
-
before = object.log_changes_formatted_value(attribute, before) || before
|
56
|
-
after = object.log_changes_formatted_value(attribute, after) || after
|
57
|
-
end
|
58
|
-
|
59
|
-
before = before.to_s if before.kind_of?(ActiveRecord::Base) || before.kind_of?(FalseClass)
|
60
|
-
after = after.to_s if after.kind_of?(ActiveRecord::Base) || after.kind_of?(FalseClass)
|
30
|
+
changes = resource_changes
|
61
31
|
|
62
|
-
|
63
|
-
object.log_changes_formatted_attribute(attribute)
|
64
|
-
end || attribute.titleize
|
65
|
-
|
66
|
-
log("#{attribute}: #{before.presence || BLANK} → #{after.presence || BLANK}", { attribute: attribute, before: before, after: after })
|
67
|
-
end
|
68
|
-
end
|
32
|
+
return true if changes.blank? # If you just click save and change nothing, don't log it.
|
69
33
|
|
70
|
-
|
71
|
-
|
34
|
+
message = (['Updated'] + changes.map do |attribute, (before, after)|
|
35
|
+
"#{attribute}: #{before.presence || BLANK} → #{after.presence || BLANK}"
|
36
|
+
end).join("\n")
|
72
37
|
|
73
|
-
|
74
|
-
resource.nested_resources.each do |association|
|
75
|
-
title = association.name.to_s.singularize.titleize
|
76
|
-
|
77
|
-
Array(object.send(association.name)).each_with_index do |child, index|
|
78
|
-
next unless child.present?
|
79
|
-
|
80
|
-
child_options = options.merge(logger: logger, depth: depth+1, prefix: "#{title} #{index} - #{child} - ", include_associated: include_associated, include_nested: include_nested)
|
81
|
-
child_options = child_options.merge(child.log_changes_options) if child.respond_to?(:log_changes_options)
|
82
|
-
|
83
|
-
@logged = true if ActiveRecordLogger.new(child, child_options).execute!
|
84
|
-
end
|
85
|
-
end
|
38
|
+
log(message, resource_attributes.merge(changes: changes))
|
86
39
|
end
|
87
40
|
|
88
41
|
def log(message, details)
|
89
|
-
|
42
|
+
Effective::Log.create!(
|
43
|
+
changes_to: log_changes_to,
|
44
|
+
associated: object,
|
45
|
+
associated_to_s: (object.to_s rescue nil),
|
90
46
|
user: EffectiveLogging.current_user,
|
91
47
|
status: EffectiveLogging.log_changes_status,
|
92
|
-
message:
|
93
|
-
associated_to_s: (logger.to_s rescue nil),
|
48
|
+
message: [options[:prefix].presence, message].compact.join,
|
94
49
|
details: (details.presence || {})
|
95
50
|
)
|
51
|
+
end
|
96
52
|
|
97
|
-
|
53
|
+
private
|
98
54
|
|
99
|
-
|
100
|
-
|
101
|
-
end
|
55
|
+
def log_changes_to
|
56
|
+
logger = object
|
102
57
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
ActiveRecordLogger.new(parent, parent_options).log(message, details)
|
58
|
+
while(logger.log_changes_options[:to].present?)
|
59
|
+
belongs_to = logger.public_send(logger.log_changes_options[:to])
|
60
|
+
break unless belongs_to.respond_to?(:log_changes_options)
|
61
|
+
logger = belongs_to
|
108
62
|
end
|
109
|
-
end
|
110
63
|
|
111
|
-
|
112
|
-
|
113
|
-
def logged?
|
114
|
-
@logged == true
|
64
|
+
logger
|
115
65
|
end
|
116
66
|
|
117
|
-
def
|
118
|
-
resource.instance_attributes(
|
67
|
+
def resource_attributes # effective_resources gem
|
68
|
+
resource.instance_attributes(only: options[:only], except: options[:except])
|
119
69
|
end
|
120
70
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
next unless parent_klass.respond_to?(:log_changes)
|
128
|
-
|
129
|
-
# Skip unless the parent accepts_nested_attributes
|
130
|
-
next unless Effective::Resource.new(parent_klass).nested_resources.find { |ass| ass.plural_name == resource.plural_name }
|
131
|
-
|
132
|
-
parent = object.public_send(association.name).presence
|
133
|
-
|
134
|
-
# Sanity check
|
135
|
-
next unless parent.respond_to?(:log_changes_options)
|
136
|
-
|
137
|
-
# Skip if the parent does not log its nested or associated items
|
138
|
-
next unless parent.log_changes_options[:include_nested] || parent.log_changes_options[:include_associated]
|
139
|
-
|
140
|
-
parent
|
141
|
-
end.compact
|
142
|
-
end
|
71
|
+
def resource_changes # effective_resources gem
|
72
|
+
resource.instance_changes(only: options[:only], except: options[:except]).inject({}) do |h, (attribute, (before, after))|
|
73
|
+
if object.respond_to?(:log_changes_formatted_value)
|
74
|
+
before = object.log_changes_formatted_value(attribute, before) || before
|
75
|
+
after = object.log_changes_formatted_value(attribute, after) || after
|
76
|
+
end
|
143
77
|
|
144
|
-
|
145
|
-
|
146
|
-
atts = if options[:only].present?
|
147
|
-
attributes.stringify_keys.slice(*options[:only])
|
148
|
-
elsif options[:except].present?
|
149
|
-
attributes.stringify_keys.except(*options[:except])
|
150
|
-
else
|
151
|
-
attributes.except(:updated_at, :created_at, 'updated_at', 'created_at')
|
152
|
-
end
|
78
|
+
before = before.to_s if before.kind_of?(ActiveRecord::Base) || before.kind_of?(FalseClass)
|
79
|
+
after = after.to_s if after.kind_of?(ActiveRecord::Base) || after.kind_of?(FalseClass)
|
153
80
|
|
154
|
-
|
155
|
-
|
156
|
-
|
81
|
+
attribute = if object.respond_to?(:log_changes_formatted_attribute)
|
82
|
+
object.log_changes_formatted_attribute(attribute)
|
83
|
+
end || attribute.to_s.titleize
|
157
84
|
|
158
|
-
|
85
|
+
h[attribute] = [before, after]; h
|
159
86
|
end
|
160
|
-
|
161
|
-
# Blacklist
|
162
|
-
atts.except(:logged_changes, :trash, :updated_at, :status_steps, 'logged_changes', 'trash', 'updated_at', 'status_steps')
|
163
|
-
end
|
164
|
-
|
165
|
-
def new_record?(object)
|
166
|
-
return true if object.respond_to?(:new_record?) && object.new_record?
|
167
|
-
return true if object.respond_to?(:id_was) && object.id_was.nil?
|
168
|
-
return true if object.respond_to?(:previous_changes) && object.previous_changes.key?('id') && object.previous_changes['id'].first.nil?
|
169
|
-
false
|
170
|
-
end
|
171
|
-
|
172
|
-
def destroyed_record?(object)
|
173
|
-
return true if object.respond_to?(:destroyed?) && object.destroyed?
|
174
|
-
return true if object.respond_to?(:marked_for_destruction?) && object.marked_for_destruction?
|
175
|
-
return true if object.respond_to?(:previous_changes) && object.previous_changes.key?('id') && object.previous_changes['id'].last.nil?
|
176
|
-
false
|
177
87
|
end
|
178
88
|
end
|
179
89
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_logging
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- app/assets/javascripts/effective_logging/effective_logger.js.coffee.erb
|
95
95
|
- app/controllers/admin/logs_controller.rb
|
96
96
|
- app/controllers/effective/logs_controller.rb
|
97
|
+
- app/datatables/effective_log_changes_datatable.rb
|
97
98
|
- app/datatables/effective_logs_datatable.rb
|
98
99
|
- app/helpers/effective_logging_helper.rb
|
99
100
|
- app/models/concerns/acts_as_loggable.rb
|