login_attack_report 0.0.3 → 0.0.4

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: 1dd891d0e15d485540c8b6690ad56b47288c7267
4
- data.tar.gz: 747abc98230549745b740726d1ae583fa21941f0
3
+ metadata.gz: 457b2c14d9c2070be1ddef5824e97a903b619acf
4
+ data.tar.gz: 86607062e97953562f55c0ae3c66f4b2d63f6191
5
5
  SHA512:
6
- metadata.gz: f52b2f4559346617cc98250f37284d7a0145852632ca0fe480a3bb446568e5e8f75463aae030e43bea319b50b1e0788fc6797c1d23c8da0feb77bbe66957f539
7
- data.tar.gz: 3a8a1c32e8fdd69ef7061511c60356a1da12d2c0bdb3df7a6c2365a1cbe3d79d10c7f821b4567bd9a74d111dd9ce2f124b88fc2dd3fe4ce7b0e9f72a4a43ecb9
6
+ metadata.gz: a421adffbb2f3b50390df3f57841bd1b48c5305a658617dbaca265887e32c8251d6c90d8b7dd3e634d7141908f68ddd8f34f3a94f7c15041e6663b290a9162ee
7
+ data.tar.gz: d263b7a9f9210ee87561db8d681bccd96dfe2f517ba1b5a0624f9e0f9d5b2aa9f2d2c86dc0f6fd3c7c684c75475ed81c8f7993781159ca04205b0a13dab78fcf
@@ -5,12 +5,7 @@ module LoginAttackReport
5
5
  extend ::ActiveSupport::Concern
6
6
 
7
7
  module ClassMethods
8
- def login_ok_limit_over
9
- # TODO config
10
- model = :User
11
- login_limit = 200
12
- login_err_limit = 50
13
-
8
+ def login_ok_limit_over(model)
14
9
  PaperTrail::Version
15
10
  .where(item_type: model)
16
11
  .where(
@@ -18,15 +13,10 @@ module LoginAttackReport
18
13
  'object_changes like \'%sign_in_count:%\'',
19
14
  Time.now.prev_month.beginning_of_month,
20
15
  Time.now.prev_month.end_of_month
21
- ).group(:item_id).having("count(item_id) > #{login_limit}")
16
+ ).group(:item_id).having("count(item_id) > #{@@login_ok_limit}")
22
17
  end
23
18
 
24
- def login_ng_limit_over
25
- # TODO config
26
- model = :User
27
- login_limit = 200
28
- login_err_limit = 50
29
-
19
+ def login_ng_limit_over(model)
30
20
  PaperTrail::Version
31
21
  .where(item_type: model)
32
22
  .where(
@@ -34,13 +24,10 @@ module LoginAttackReport
34
24
  'object_changes like \'%sign_in_count:%\'',
35
25
  Time.now.prev_month.beginning_of_month,
36
26
  Time.now.prev_month.end_of_month
37
- ).group(:item_id).having("count(item_id) > #{login_limit}")
27
+ ).group(:item_id).having("count(item_id) > #{@@login_ng_limit}")
38
28
  end
39
- def ip_limit_over
40
- # TODO config
41
- model = :User
42
- login_limit = 200
43
- login_err_limit = 50
29
+
30
+ def ip_limit_over(model)
44
31
  alert_ip_limit_over = PaperTrail::Version
45
32
  .where(item_type: model)
46
33
  .where(
@@ -1,3 +1,3 @@
1
1
  module LoginAttackReport
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -2,21 +2,16 @@ require 'login_attack_report/version'
2
2
  require 'active_support'
3
3
  require 'active_record'
4
4
  require 'paper_trail'
5
- require 'rails'
6
5
 
7
6
  Dir[File.join(File.dirname(__FILE__), 'login_attack_report', '*.rb')].each do |file|
8
7
  require File.join('login_attack_report', File.basename(file, '.rb'))
9
8
  end
10
9
  require 'login_attack_report/frameworks/active_record'
11
- require 'login_attack_report/frameworks/rails'
12
10
 
13
11
  module LoginAttackReport
14
- # Your code goes here...
15
- def self.new_method # "call new_method"という文字列を返すだけのメソッド
16
- "call new_method"
17
- end
18
- end
12
+ mattr_accessor :login_ok_limit
13
+ @@login_ok_limit = 200
19
14
 
20
- ActiveSupport.on_load(:active_record) do
21
- include LoginAttackReport::Model
15
+ mattr_accessor :login_ng_limit
16
+ @@login_ng_limit = 50
22
17
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: login_attack_report
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - taru m
@@ -177,9 +177,6 @@ files:
177
177
  - lib/login_attack_report.rb
178
178
  - lib/login_attack_report/frameworks/active_record.rb
179
179
  - lib/login_attack_report/frameworks/active_record/models/login_attack_report_version.rb
180
- - lib/login_attack_report/frameworks/rails.rb
181
- - lib/login_attack_report/frameworks/rails/engine.rb
182
- - lib/login_attack_report/has_login_attack_report.rb
183
180
  - lib/login_attack_report/login_attack_report_version_concern.rb
184
181
  - lib/login_attack_report/version.rb
185
182
  - login_attack_report.gemspec
@@ -1,7 +0,0 @@
1
- module LoginAttackReport
2
- module Rails
3
- class Engine < ::Rails::Engine
4
- paths['app/models'] << 'lib/login_attack_report/frameworks/active_record/models'
5
- end
6
- end
7
- end
@@ -1,6 +0,0 @@
1
- require 'login_attack_report/frameworks/rails/engine'
2
-
3
- module LoginAttackReport
4
- module Rails
5
- end
6
- end
@@ -1,504 +0,0 @@
1
- require 'active_support/core_ext/object' # provides the `try` method
2
-
3
- module LoginAttackReport
4
- module Model
5
-
6
- def self.included(base)
7
- base.send :extend, ClassMethods
8
- end
9
-
10
- module ClassMethods
11
- # Declare this in your model to track every create, update, and destroy. Each version of
12
- # the model is available in the `versions` association.
13
- #
14
- # Options:
15
- # :on the events to track (optional; defaults to all of them). Set to an array of
16
- # `:create`, `:update`, `:destroy` as desired.
17
- # :class_name the name of a custom Version class. This class should inherit from `PaperTrail::Version`.
18
- # :ignore an array of attributes for which a new `Version` will not be created if only they change.
19
- # it can also aceept a Hash as an argument where the key is the attribute to ignore (a `String` or `Symbol`),
20
- # which will only be ignored if the value is a `Proc` which returns truthily.
21
- # :if, :unless Procs that allow to specify conditions when to save versions for an object
22
- # :only inverse of `ignore` - a new `Version` will be created only for these attributes if supplied
23
- # it can also aceept a Hash as an argument where the key is the attribute to track (a `String` or `Symbol`),
24
- # which will only be counted if the value is a `Proc` which returns truthily.
25
- # :skip fields to ignore completely. As with `ignore`, updates to these fields will not create
26
- # a new `Version`. In addition, these fields will not be included in the serialized versions
27
- # of the object whenever a new `Version` is created.
28
- # :meta a hash of extra data to store. You must add a column to the `versions` table for each key.
29
- # Values are objects or procs (which are called with `self`, i.e. the model with the paper
30
- # trail). See `PaperTrail::Controller.info_for_paper_trail` for how to store data from
31
- # the controller.
32
- # :versions the name to use for the versions association. Default is `:versions`.
33
- # :version the name to use for the method which returns the version the instance was reified from.
34
- # Default is `:version`.
35
- # :save_changes whether or not to save changes to the object_changes column if it exists. Default is true
36
- #
37
- def has_paper_trail(options = {})
38
- # Lazily include the instance methods so we don't clutter up
39
- # any more ActiveRecord models than we have to.
40
- send :include, InstanceMethods
41
-
42
- class_attribute :version_association_name
43
- self.version_association_name = options[:version] || :version
44
-
45
- # The version this instance was reified from.
46
- attr_accessor self.version_association_name
47
-
48
- class_attribute :version_class_name
49
- self.version_class_name = options[:class_name] || 'PaperTrail::Version'
50
-
51
- class_attribute :paper_trail_options
52
- self.paper_trail_options = options.dup
53
-
54
- [:ignore, :skip, :only].each do |k|
55
- paper_trail_options[k] =
56
- [paper_trail_options[k]].flatten.compact.map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
57
- end
58
-
59
- paper_trail_options[:meta] ||= {}
60
- paper_trail_options[:save_changes] = true if paper_trail_options[:save_changes].nil?
61
-
62
- class_attribute :versions_association_name
63
- self.versions_association_name = options[:versions] || :versions
64
-
65
- attr_accessor :paper_trail_event
66
-
67
- if ::ActiveRecord::VERSION::MAJOR >= 4 # `has_many` syntax for specifying order uses a lambda in Rails 4
68
- has_many self.versions_association_name,
69
- lambda { order(model.timestamp_sort_order) },
70
- :class_name => self.version_class_name, :as => :item
71
- else
72
- has_many self.versions_association_name,
73
- :class_name => self.version_class_name,
74
- :as => :item,
75
- :order => self.paper_trail_version_class.timestamp_sort_order
76
- end
77
-
78
- options[:on] ||= [:create, :update, :destroy]
79
- options_on = Array(options[:on]) # so that a single symbol can be passed in without wrapping it in an `Array`
80
- after_create :record_create, :if => :save_version? if options_on.include?(:create)
81
- if options_on.include?(:update)
82
- before_save :reset_timestamp_attrs_for_update_if_needed!, :on => :update
83
- after_update :record_update, :if => :save_version?
84
- after_update :clear_version_instance!
85
- end
86
- after_destroy :record_destroy, :if => :save_version? if options_on.include?(:destroy)
87
-
88
- # Reset the transaction id when the transaction is closed
89
- after_commit :reset_transaction_id
90
- after_rollback :reset_transaction_id
91
- after_rollback :clear_rolled_back_versions
92
- end
93
-
94
- # Switches PaperTrail off for this class.
95
- def paper_trail_off!
96
- PaperTrail.enabled_for_model(self, false)
97
- end
98
-
99
- def paper_trail_off
100
- warn "DEPRECATED: use `paper_trail_off!` instead of `paper_trail_off`. Support for `paper_trail_off` will be removed in PaperTrail 4.0"
101
- self.paper_trail_off!
102
- end
103
-
104
- # Switches PaperTrail on for this class.
105
- def paper_trail_on!
106
- PaperTrail.enabled_for_model(self, true)
107
- end
108
-
109
- def paper_trail_on
110
- warn "DEPRECATED: use `paper_trail_on!` instead of `paper_trail_on`. Support for `paper_trail_on` will be removed in PaperTrail 4.0"
111
- self.paper_trail_on!
112
- end
113
-
114
- def paper_trail_enabled_for_model?
115
- return false unless self.include?(PaperTrail::Model::InstanceMethods)
116
- PaperTrail.enabled_for_model?(self)
117
- end
118
-
119
- def paper_trail_version_class
120
- @paper_trail_version_class ||= version_class_name.constantize
121
- end
122
-
123
- # Used for Version#object attribute
124
- def serialize_attributes_for_paper_trail!(attributes)
125
- # don't serialize before values before inserting into columns of type `JSON` on `PostgreSQL` databases
126
- return attributes if self.paper_trail_version_class.object_col_is_json?
127
-
128
- serialized_attributes.each do |key, coder|
129
- if attributes.key?(key)
130
- # Fall back to current serializer if `coder` has no `dump` method
131
- coder = PaperTrail.serializer unless coder.respond_to?(:dump)
132
- attributes[key] = coder.dump(attributes[key])
133
- end
134
- end
135
- end
136
-
137
- def unserialize_attributes_for_paper_trail!(attributes)
138
- # don't serialize before values before inserting into columns of type `JSON` on `PostgreSQL` databases
139
- return attributes if self.paper_trail_version_class.object_col_is_json?
140
-
141
- serialized_attributes.each do |key, coder|
142
- if attributes.key?(key)
143
- coder = PaperTrail.serializer unless coder.respond_to?(:dump)
144
- attributes[key] = coder.load(attributes[key])
145
- end
146
- end
147
- end
148
-
149
- # Used for Version#object_changes attribute
150
- def serialize_attribute_changes_for_paper_trail!(changes)
151
- # don't serialize before values before inserting into columns of type `JSON` on `PostgreSQL` databases
152
- return changes if self.paper_trail_version_class.object_changes_col_is_json?
153
-
154
- serialized_attributes.each do |key, coder|
155
- if changes.key?(key)
156
- # Fall back to current serializer if `coder` has no `dump` method
157
- coder = PaperTrail.serializer unless coder.respond_to?(:dump)
158
- old_value, new_value = changes[key]
159
- changes[key] = [coder.dump(old_value),
160
- coder.dump(new_value)]
161
- end
162
- end
163
- end
164
-
165
- def unserialize_attribute_changes_for_paper_trail!(changes)
166
- # don't serialize before values before inserting into columns of type `JSON` on `PostgreSQL` databases
167
- return changes if self.paper_trail_version_class.object_changes_col_is_json?
168
-
169
- serialized_attributes.each do |key, coder|
170
- if changes.key?(key)
171
- coder = PaperTrail.serializer unless coder.respond_to?(:dump)
172
- old_value, new_value = changes[key]
173
- changes[key] = [coder.load(old_value),
174
- coder.load(new_value)]
175
- end
176
- end
177
- end
178
- end
179
-
180
- # Wrap the following methods in a module so we can include them only in the
181
- # ActiveRecord models that declare `has_paper_trail`.
182
- module InstanceMethods
183
- # Returns true if this instance is the current, live one;
184
- # returns false if this instance came from a previous version.
185
- def live?
186
- source_version.nil?
187
- end
188
-
189
- # Returns who put the object into its current state.
190
- def paper_trail_originator
191
- (source_version || send(self.class.versions_association_name).last).try(:whodunnit)
192
- end
193
-
194
- def originator
195
- warn "DEPRECATED: use `paper_trail_originator` instead of `originator`. Support for `originator` will be removed in PaperTrail 4.0"
196
- self.paper_trail_originator
197
- end
198
-
199
- # Invoked after rollbacks to ensure versions records are not created
200
- # for changes that never actually took place
201
- def clear_rolled_back_versions
202
- send(self.class.versions_association_name).reload
203
- end
204
-
205
- # Returns the object (not a Version) as it was at the given timestamp.
206
- def version_at(timestamp, reify_options={})
207
- # Because a version stores how its object looked *before* the change,
208
- # we need to look for the first version created *after* the timestamp.
209
- v = send(self.class.versions_association_name).subsequent(timestamp, true).first
210
- return v.reify(reify_options) if v
211
- self unless self.destroyed?
212
- end
213
-
214
- # Returns the objects (not Versions) as they were between the given times.
215
- def versions_between(start_time, end_time, reify_options={})
216
- versions = send(self.class.versions_association_name).between(start_time, end_time)
217
- versions.collect { |version| version_at(version.send PaperTrail.timestamp_field) }
218
- end
219
-
220
- # Returns the object (not a Version) as it was most recently.
221
- def previous_version
222
- preceding_version = source_version ? source_version.previous : send(self.class.versions_association_name).last
223
- preceding_version.reify if preceding_version
224
- end
225
-
226
- # Returns the object (not a Version) as it became next.
227
- # NOTE: if self (the item) was not reified from a version, i.e. it is the
228
- # "live" item, we return nil. Perhaps we should return self instead?
229
- def next_version
230
- subsequent_version = source_version.next
231
- subsequent_version ? subsequent_version.reify : self.class.find(self.id)
232
- rescue
233
- nil
234
- end
235
-
236
- def paper_trail_enabled_for_model?
237
- self.class.paper_trail_enabled_for_model?
238
- end
239
-
240
- # Executes the given method or block without creating a new version.
241
- def without_versioning(method = nil)
242
- paper_trail_was_enabled = self.paper_trail_enabled_for_model?
243
- self.class.paper_trail_off!
244
- method ? method.to_proc.call(self) : yield(self)
245
- ensure
246
- self.class.paper_trail_on! if paper_trail_was_enabled
247
- end
248
-
249
- # Utility method for reifying. Anything executed inside the block will appear like a new record
250
- def appear_as_new_record
251
- instance_eval {
252
- alias :old_new_record? :new_record?
253
- alias :new_record? :present?
254
- }
255
- yield
256
- instance_eval { alias :new_record? :old_new_record? }
257
- end
258
-
259
- # Temporarily overwrites the value of whodunnit and then executes the provided block.
260
- def whodunnit(value)
261
- raise ArgumentError, 'expected to receive a block' unless block_given?
262
- current_whodunnit = PaperTrail.whodunnit
263
- PaperTrail.whodunnit = value
264
- yield self
265
- ensure
266
- PaperTrail.whodunnit = current_whodunnit
267
- end
268
-
269
- # Mimicks behavior of `touch` method from `ActiveRecord::Persistence`, but generates a version
270
- #
271
- # TODO: lookinto leveraging the `after_touch` callback from `ActiveRecord` to allow the
272
- # regular `touch` method go generate a version as normal. May make sense to switch the `record_update`
273
- # method to leverage an `after_update` callback anyways (likely for v4.0.0)
274
- def touch_with_version(name = nil)
275
- raise ActiveRecordError, "can not touch on a new record object" unless persisted?
276
-
277
- attributes = timestamp_attributes_for_update_in_model
278
- attributes << name if name
279
- current_time = current_time_from_proper_timezone
280
-
281
- attributes.each { |column| write_attribute(column, current_time) }
282
- # ensure a version is written even if the `:on` collection is empty
283
- record_update(true) if paper_trail_options[:on] == []
284
- save!(:validate => false)
285
- end
286
-
287
- private
288
-
289
- def source_version
290
- send self.class.version_association_name
291
- end
292
-
293
- def record_create
294
- if paper_trail_switched_on?
295
- data = {
296
- :event => paper_trail_event || 'create',
297
- :whodunnit => PaperTrail.whodunnit
298
- }
299
- if respond_to?(:created_at)
300
- data[PaperTrail.timestamp_field] = created_at
301
- end
302
- if paper_trail_options[:save_changes] && changed_notably? && self.class.paper_trail_version_class.column_names.include?('object_changes')
303
- data[:object_changes] = self.class.paper_trail_version_class.object_changes_col_is_json? ? changes_for_paper_trail :
304
- PaperTrail.serializer.dump(changes_for_paper_trail)
305
- end
306
- if self.class.paper_trail_version_class.column_names.include?('transaction_id')
307
- data[:transaction_id] = PaperTrail.transaction_id
308
- end
309
- version = send(self.class.versions_association_name).create! merge_metadata(data)
310
- set_transaction_id(version)
311
- save_associations(version)
312
- end
313
- end
314
-
315
- def record_update(force = nil)
316
- if paper_trail_switched_on? && (force || changed_notably?)
317
- object_attrs = object_attrs_for_paper_trail(attributes_before_change)
318
- data = {
319
- :event => paper_trail_event || 'update',
320
- :object => self.class.paper_trail_version_class.object_col_is_json? ? object_attrs : PaperTrail.serializer.dump(object_attrs),
321
- :whodunnit => PaperTrail.whodunnit
322
- }
323
- if respond_to?(:updated_at)
324
- data[PaperTrail.timestamp_field] = updated_at
325
- end
326
- if paper_trail_options[:save_changes] && self.class.paper_trail_version_class.column_names.include?('object_changes')
327
- data[:object_changes] = self.class.paper_trail_version_class.object_changes_col_is_json? ? changes_for_paper_trail :
328
- PaperTrail.serializer.dump(changes_for_paper_trail)
329
- end
330
- if self.class.paper_trail_version_class.column_names.include?('transaction_id')
331
- data[:transaction_id] = PaperTrail.transaction_id
332
- end
333
- version = send(self.class.versions_association_name).create merge_metadata(data)
334
- set_transaction_id(version)
335
- save_associations(version)
336
- end
337
- end
338
-
339
- def changes_for_paper_trail
340
- _changes = changes.delete_if { |k,v| !notably_changed.include?(k) }
341
- if PaperTrail.serialized_attributes?
342
- self.class.serialize_attribute_changes_for_paper_trail!(_changes)
343
- end
344
- _changes.to_hash
345
- end
346
-
347
- # Invoked via`after_update` callback for when a previous version is reified and then saved
348
- def clear_version_instance!
349
- send("#{self.class.version_association_name}=", nil)
350
- end
351
-
352
- def reset_timestamp_attrs_for_update_if_needed!
353
- return if self.live? # invoked via callback when a user attempts to persist a reified `Version`
354
- timestamp_attributes_for_update_in_model.each do |column|
355
- # ActiveRecord 4.2 deprecated `reset_column!` in favor of `restore_column!`
356
- if respond_to?("restore_#{column}!")
357
- send("restore_#{column}!")
358
- else
359
- send("reset_#{column}!")
360
- end
361
- end
362
- end
363
-
364
- def record_destroy
365
- if paper_trail_switched_on? and not new_record?
366
- object_attrs = object_attrs_for_paper_trail(attributes_before_change)
367
- data = {
368
- :item_id => self.id,
369
- :item_type => self.class.base_class.name,
370
- :event => paper_trail_event || 'destroy',
371
- :object => self.class.paper_trail_version_class.object_col_is_json? ? object_attrs : PaperTrail.serializer.dump(object_attrs),
372
- :whodunnit => PaperTrail.whodunnit
373
- }
374
- if self.class.paper_trail_version_class.column_names.include?('transaction_id')
375
- data[:transaction_id] = PaperTrail.transaction_id
376
- end
377
- version = self.class.paper_trail_version_class.create(merge_metadata(data))
378
- send("#{self.class.version_association_name}=", version)
379
- send(self.class.versions_association_name).send :load_target
380
- set_transaction_id(version)
381
- save_associations(version)
382
- end
383
- end
384
-
385
- # saves associations if the join table for `VersionAssociation` exists
386
- def save_associations(version)
387
- return unless PaperTrail.config.track_associations?
388
- self.class.reflect_on_all_associations(:belongs_to).each do |assoc|
389
- assoc_version_args = {
390
- :version_id => version.id,
391
- :foreign_key_name => assoc.foreign_key
392
- }
393
-
394
- if assoc.options[:polymorphic]
395
- associated_record = send(assoc.name) if send(assoc.foreign_type)
396
- if associated_record && associated_record.class.paper_trail_enabled_for_model?
397
- assoc_version_args.merge!(:foreign_key_id => associated_record.id)
398
- end
399
- elsif assoc.klass.paper_trail_enabled_for_model?
400
- assoc_version_args.merge!(:foreign_key_id => send(assoc.foreign_key))
401
- end
402
-
403
- PaperTrail::VersionAssociation.create(assoc_version_args) if assoc_version_args.has_key?(:foreign_key_id)
404
- end
405
- end
406
-
407
- def set_transaction_id(version)
408
- return unless self.class.paper_trail_version_class.column_names.include?('transaction_id')
409
- if PaperTrail.transaction? && PaperTrail.transaction_id.nil?
410
- PaperTrail.transaction_id = version.id
411
- version.transaction_id = version.id
412
- version.save
413
- end
414
- end
415
-
416
- def reset_transaction_id
417
- PaperTrail.transaction_id = nil
418
- end
419
-
420
- def merge_metadata(data)
421
- # First we merge the model-level metadata in `meta`.
422
- paper_trail_options[:meta].each do |k,v|
423
- data[k] =
424
- if v.respond_to?(:call)
425
- v.call(self)
426
- elsif v.is_a?(Symbol) && respond_to?(v)
427
- # if it is an attribute that is changing in an existing object,
428
- # be sure to grab the current version
429
- if has_attribute?(v) && send("#{v}_changed?".to_sym) && data[:event] != 'create'
430
- send("#{v}_was".to_sym)
431
- else
432
- send(v)
433
- end
434
- else
435
- v
436
- end
437
- end
438
- # Second we merge any extra data from the controller (if available).
439
- data.merge(PaperTrail.controller_info || {})
440
- end
441
-
442
- def attributes_before_change
443
- attributes.tap do |prev|
444
- enums = self.respond_to?(:defined_enums) ? self.defined_enums : {}
445
- changed_attributes.select { |k,v| self.class.column_names.include?(k) }.each do |attr, before|
446
- before = enums[attr][before] if enums[attr]
447
- prev[attr] = before
448
- end
449
- end
450
- end
451
-
452
- # returns hash of attributes (with appropriate attributes serialized),
453
- # ommitting attributes to be skipped
454
- def object_attrs_for_paper_trail(attributes_hash)
455
- attrs = attributes_hash.except(*self.paper_trail_options[:skip])
456
- if PaperTrail.serialized_attributes?
457
- self.class.serialize_attributes_for_paper_trail!(attrs)
458
- end
459
- attrs
460
- end
461
-
462
- # This method is invoked in order to determine whether it is appropriate to generate a new version instance.
463
- # Because we are now using `after_(create/update/etc)` callbacks, we need to go out of our way to
464
- # ensure that during updates timestamp attributes are not acknowledged as a notable changes
465
- # to raise false positives when attributes are ignored.
466
- def changed_notably?
467
- if self.paper_trail_options[:ignore].any? && (changed & self.paper_trail_options[:ignore]).any?
468
- (notably_changed - timestamp_attributes_for_update_in_model.map(&:to_s)).any?
469
- else
470
- notably_changed.any?
471
- end
472
- end
473
-
474
- def notably_changed
475
- only = self.paper_trail_options[:only].dup
476
- # remove Hash arguments and then evaluate whether the attributes (the keys of the hash) should also get pushed into the collection
477
- only.delete_if do |obj|
478
- obj.is_a?(Hash) && obj.each { |attr, condition| only << attr if condition.respond_to?(:call) && condition.call(self) }
479
- end
480
- only.empty? ? changed_and_not_ignored : (changed_and_not_ignored & only)
481
- end
482
-
483
- def changed_and_not_ignored
484
- ignore = self.paper_trail_options[:ignore].dup
485
- # remove Hash arguments and then evaluate whether the attributes (the keys of the hash) should also get pushed into the collection
486
- ignore.delete_if do |obj|
487
- obj.is_a?(Hash) && obj.each { |attr, condition| ignore << attr if condition.respond_to?(:call) && condition.call(self) }
488
- end
489
- skip = self.paper_trail_options[:skip]
490
- changed - ignore - skip
491
- end
492
-
493
- def paper_trail_switched_on?
494
- PaperTrail.enabled? && PaperTrail.enabled_for_controller? && self.paper_trail_enabled_for_model?
495
- end
496
-
497
- def save_version?
498
- if_condition = self.paper_trail_options[:if]
499
- unless_condition = self.paper_trail_options[:unless]
500
- (if_condition.blank? || if_condition.call(self)) && !unless_condition.try(:call, self)
501
- end
502
- end
503
- end
504
- end