mirror of
https://github.com/paper-trail-gem/paper_trail.git
synced 2022-11-09 11:33:19 -05:00
legacy complient callback-methods
This commit is contained in:
parent
9008d673a5
commit
297f5fcac0
7 changed files with 108 additions and 43 deletions
|
@ -1,40 +1,34 @@
|
||||||
module PaperTrail
|
module PaperTrail
|
||||||
module Callbacks
|
module Callbacks
|
||||||
def setup_callbacks_from_options(options_on, options = {})
|
# The cleanup_* methods are only used to provide backward-compatibility
|
||||||
|
# They should be removed as soon as the "traditional" way of using
|
||||||
|
# PaperTrail `has_papertrail :on => [...]` with or without the :on option
|
||||||
|
# and not setting the paper_trail_* methods is no longer supported.
|
||||||
|
def setup_callbacks_from_options(options_on = [])
|
||||||
options_on.each do |option|
|
options_on.each do |option|
|
||||||
send "paper_trail_#{option}", options
|
send "paper_trail_on_#{option}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
paper_trail_options[:on] = options_on
|
||||||
end
|
end
|
||||||
|
|
||||||
# Record version before or after "destroy" event
|
# Record version before or after "destroy" event
|
||||||
def paper_trail_destroy(options = {})
|
def paper_trail_on_destroy(recording_order = 'after')
|
||||||
setup_model_if_necessary options
|
|
||||||
recording_order = options[:recording_order] || 'after'
|
|
||||||
|
|
||||||
unless %(after before).include?(recording_order.to_s)
|
unless %(after before).include?(recording_order.to_s)
|
||||||
fail ArgumentError, 'recording order can only be "after" or "before"'
|
fail ArgumentError, 'recording order can only be "after" or "before"'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cleanup_callback_chain
|
||||||
|
|
||||||
send "#{recording_order}_destroy",
|
send "#{recording_order}_destroy",
|
||||||
:record_destroy,
|
:record_destroy,
|
||||||
:if => :save_version?
|
:if => :save_version?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Record version after "destroy" event
|
|
||||||
def paper_trail_after_destroy(options = {})
|
|
||||||
options[:recording_order] = :after
|
|
||||||
paper_trail_destroy options
|
|
||||||
end
|
|
||||||
|
|
||||||
# Record version before "destroy" event
|
|
||||||
def paper_trail_before_destroy(options = {})
|
|
||||||
options[:recording_order] = :before
|
|
||||||
paper_trail_destroy options
|
|
||||||
end
|
|
||||||
|
|
||||||
# Record version after "update" event
|
# Record version after "update" event
|
||||||
def paper_trail_update(options = {})
|
def paper_trail_on_update
|
||||||
setup_model_if_necessary options
|
cleanup_callback_chain
|
||||||
|
|
||||||
before_save :reset_timestamp_attrs_for_update_if_needed!,
|
before_save :reset_timestamp_attrs_for_update_if_needed!,
|
||||||
:on => :update
|
:on => :update
|
||||||
after_update :record_update,
|
after_update :record_update,
|
||||||
|
@ -43,23 +37,64 @@ module PaperTrail
|
||||||
end
|
end
|
||||||
|
|
||||||
# Record version after "create" event
|
# Record version after "create" event
|
||||||
def paper_trail_create(options = {})
|
def paper_trail_on_create
|
||||||
setup_model_if_necessary options
|
cleanup_callback_chain
|
||||||
|
|
||||||
after_create :record_create,
|
after_create :record_create,
|
||||||
:if => :save_version?
|
:if => :save_version?
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def setup_model_if_necessary(options)
|
# The cleanup_* methods are only used to provide backward-compatibility
|
||||||
return true if model_set_up?
|
# They should be removed as soon as the "traditional" way of using
|
||||||
|
# PaperTrail `has_papertrail :on => [...]` with or without the :on option
|
||||||
setup_model_for_paper_trail options
|
# and not setting the paper_trail_* methods is no longer supported.
|
||||||
@_set_up = true
|
def cleanup_callback_chain
|
||||||
|
on_options = paper_trail_options.try(:delete, :on) || []
|
||||||
|
on_options.each do |on_option|
|
||||||
|
send "cleanup_#{on_option}_callbacks"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_set_up?
|
def cleanup_create_callbacks
|
||||||
@_set_up
|
callback =
|
||||||
|
_create_callbacks.find do |cb|
|
||||||
|
cb.filter.eql?(:record_create) && cb.kind.eql?(:after)
|
||||||
|
end
|
||||||
|
|
||||||
|
_create_callbacks.delete(callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup_update_callbacks
|
||||||
|
callback =
|
||||||
|
_save_callbacks.find do |cb|
|
||||||
|
cb.filter.eql?(:reset_timestamp_attrs_for_update_if_needed!) && cb.kind.eql?(:before)
|
||||||
|
end
|
||||||
|
|
||||||
|
_save_callbacks.delete(callback)
|
||||||
|
|
||||||
|
callback =
|
||||||
|
_update_callbacks.find do |cb|
|
||||||
|
cb.filter.eql?(:record_update) && cb.kind.eql?(:after)
|
||||||
|
end
|
||||||
|
|
||||||
|
_update_callbacks.delete(callback)
|
||||||
|
callback =
|
||||||
|
_update_callbacks.find do |cb|
|
||||||
|
cb.filter.eql?(:clear_version_instance!) && cb.kind.eql?(:after)
|
||||||
|
end
|
||||||
|
|
||||||
|
_update_callbacks.delete(callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup_destroy_callbacks
|
||||||
|
callback =
|
||||||
|
_destroy_callbacks.find do |cb|
|
||||||
|
cb.filter.eql?(:record_destroy)
|
||||||
|
end
|
||||||
|
|
||||||
|
_destroy_callbacks.delete(callback)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,15 +48,26 @@ module PaperTrail
|
||||||
# column if it exists. Default is true
|
# column if it exists. Default is true
|
||||||
#
|
#
|
||||||
def has_paper_trail(options = {})
|
def has_paper_trail(options = {})
|
||||||
setup_model_for_paper_trail(options)
|
# Initializing paper_trail_options with an empty hash before setting
|
||||||
|
# up the callback-methods is important to make them compatible with the
|
||||||
|
# traditional has_paper_trail method.
|
||||||
|
# This can move to setup_model_for_paper_trail, as soon as the
|
||||||
|
# cleanup_callback and setup_callbacks_from_options method is no longer
|
||||||
|
# needed.
|
||||||
|
class_attribute :paper_trail_options
|
||||||
|
self.paper_trail_options = {}
|
||||||
|
|
||||||
|
# TODO: Add a deprecation warning / info to use callback methods instead
|
||||||
|
# of the :on option?
|
||||||
options[:on] ||= [:create, :update, :destroy]
|
options[:on] ||= [:create, :update, :destroy]
|
||||||
|
|
||||||
# Wrap the :on option in an array if necessary. This allows a single
|
# Wrap the :on option in an array if necessary. This allows a single
|
||||||
# symbol to be passed in.
|
# symbol to be passed in.
|
||||||
options_on = Array(options[:on])
|
options_on = Array(options[:on])
|
||||||
|
|
||||||
setup_callbacks_from_options options_on, options
|
setup_callbacks_from_options options_on
|
||||||
|
|
||||||
|
setup_model_for_paper_trail(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_model_for_paper_trail(options = {})
|
def setup_model_for_paper_trail(options = {})
|
||||||
|
@ -73,7 +84,6 @@ module PaperTrail
|
||||||
class_attribute :version_class_name
|
class_attribute :version_class_name
|
||||||
self.version_class_name = options[:class_name] || 'PaperTrail::Version'
|
self.version_class_name = options[:class_name] || 'PaperTrail::Version'
|
||||||
|
|
||||||
class_attribute :paper_trail_options
|
|
||||||
self.paper_trail_options = options.dup
|
self.paper_trail_options = options.dup
|
||||||
|
|
||||||
[:ignore, :skip, :only].each do |k|
|
[:ignore, :skip, :only].each do |k|
|
||||||
|
|
|
@ -15,5 +15,22 @@ describe Animal, :type => :model do
|
||||||
expect(dog).to be_instance_of(Dog)
|
expect(dog).to be_instance_of(Dog)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with callback-methods' do
|
||||||
|
context 'when only has_paper_trail set in super class' do
|
||||||
|
let(:callback_cat) { Cat.create(:name => 'Markus') }
|
||||||
|
|
||||||
|
it 'trails all events' do
|
||||||
|
callback_cat.update_attributes(:name => 'Billie')
|
||||||
|
callback_cat.destroy
|
||||||
|
expect(callback_cat.versions.collect(&:event)).to eq %w(create update destroy)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not break reify' do
|
||||||
|
callback_cat.destroy
|
||||||
|
expect { callback_cat.versions.last.reify }.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,7 +69,7 @@ describe CallbackModifier, :type => :model do
|
||||||
modifier = CreateModifier.create!(:some_content => Faker::Lorem.sentence)
|
modifier = CreateModifier.create!(:some_content => Faker::Lorem.sentence)
|
||||||
modifier.update_attributes!(:some_content => 'modified')
|
modifier.update_attributes!(:some_content => 'modified')
|
||||||
modifier.test_destroy
|
modifier.test_destroy
|
||||||
expect(modifier.versions.last.event).to eq 'create'
|
expect(modifier.versions.collect(&:event)).to eq ['create']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,6 +37,8 @@ RSpec.configure do |config|
|
||||||
# `true` in RSpec 4.
|
# `true` in RSpec 4.
|
||||||
mocks.verify_partial_doubles = true
|
mocks.verify_partial_doubles = true
|
||||||
end
|
end
|
||||||
|
config.filter_run :focus
|
||||||
|
config.run_all_when_everything_filtered = true
|
||||||
|
|
||||||
# The settings below are suggested to provide a good initial experience
|
# The settings below are suggested to provide a good initial experience
|
||||||
# with RSpec, but feel free to customize to your heart's content.
|
# with RSpec, but feel free to customize to your heart's content.
|
||||||
|
@ -45,8 +47,6 @@ RSpec.configure do |config|
|
||||||
# to individual examples or groups you care about by tagging them with
|
# to individual examples or groups you care about by tagging them with
|
||||||
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
||||||
# get run.
|
# get run.
|
||||||
config.filter_run :focus
|
|
||||||
config.run_all_when_everything_filtered = true
|
|
||||||
|
|
||||||
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
||||||
# For more details, see:
|
# For more details, see:
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
class BeforeDestroyModifier < CallbackModifier
|
class BeforeDestroyModifier < CallbackModifier
|
||||||
paper_trail_before_destroy
|
has_paper_trail
|
||||||
|
paper_trail_on_destroy :before
|
||||||
end
|
end
|
||||||
|
|
||||||
class AfterDestroyModifier < CallbackModifier
|
class AfterDestroyModifier < CallbackModifier
|
||||||
paper_trail_after_destroy
|
has_paper_trail
|
||||||
|
paper_trail_on_destroy :after
|
||||||
end
|
end
|
||||||
|
|
||||||
class NoArgDestroyModifier < CallbackModifier
|
class NoArgDestroyModifier < CallbackModifier
|
||||||
paper_trail_destroy
|
has_paper_trail
|
||||||
|
paper_trail_on_destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
class UpdateModifier < CallbackModifier
|
class UpdateModifier < CallbackModifier
|
||||||
paper_trail_update
|
paper_trail_on_update
|
||||||
end
|
end
|
||||||
|
|
||||||
class CreateModifier < CallbackModifier
|
class CreateModifier < CallbackModifier
|
||||||
paper_trail_create
|
paper_trail_on_create
|
||||||
end
|
end
|
||||||
|
|
||||||
class DefaultModifier < CallbackModifier
|
class DefaultModifier < CallbackModifier
|
||||||
|
# Because of the way I set up the destroy method for testing
|
||||||
|
# has_paper_trail has to be initialized in this model seperately
|
||||||
has_paper_trail
|
has_paper_trail
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
class CallbackModifier < ActiveRecord::Base
|
class CallbackModifier < ActiveRecord::Base
|
||||||
# This will not be directly instantiated, but we need to set paper_trail up
|
has_paper_trail
|
||||||
# before we can run tests on fake classes inheriting from CallbackModifier
|
|
||||||
has_paper_trail :on => []
|
|
||||||
|
|
||||||
def test_destroy
|
def test_destroy
|
||||||
transaction do
|
transaction do
|
||||||
|
|
Loading…
Reference in a new issue