1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix collisions with before and after validation callbacks.

This commit allows a user to do something like:
    before_validation :do_stuff, :on => [ :create, :update ]
    after_validation :do_more, :on => [ :create, :update ]
This commit is contained in:
John Foley 2012-07-02 10:18:12 -06:00
parent 09d298eecc
commit d66d6076b2
2 changed files with 55 additions and 2 deletions

View file

@ -56,7 +56,8 @@ module ActiveModel
options = args.last options = args.last
if options.is_a?(Hash) && options[:on] if options.is_a?(Hash) && options[:on]
options[:if] = Array(options[:if]) options[:if] = Array(options[:if])
options[:if].unshift("self.validation_context == :#{options[:on]}") options[:on] = Array(options[:on])
options[:if].unshift("self.validation_context.in? #{options[:on]}")
end end
set_callback(:validation, :before, *args, &block) set_callback(:validation, :before, *args, &block)
end end
@ -92,7 +93,10 @@ module ActiveModel
options = args.extract_options! options = args.extract_options!
options[:prepend] = true options[:prepend] = true
options[:if] = Array(options[:if]) options[:if] = Array(options[:if])
options[:if].unshift("self.validation_context == :#{options[:on]}") if options[:on] if options[:on]
options[:on] = Array(options[:on])
options[:if].unshift("self.validation_context.in? #{options[:on]}")
end
set_callback(:validation, :after, *(args << options), &block) set_callback(:validation, :after, *(args << options), &block)
end end
end end

View file

@ -137,6 +137,32 @@ class OnCallbacksDeveloper < ActiveRecord::Base
end end
end end
class ContextualCallbacksDeveloper < ActiveRecord::Base
self.table_name = 'developers'
before_validation { history << :before_validation }
before_validation :before_validation_on_create_and_update, :on => [ :create, :update ]
validate do
history << :validate
end
after_validation { history << :after_validation }
after_validation :after_validation_on_create_and_update, :on => [ :create, :update ]
def before_validation_on_create_and_update
history << "before_validation_on_#{self.validation_context}".to_sym
end
def after_validation_on_create_and_update
history << "after_validation_on_#{self.validation_context}".to_sym
end
def history
@history ||= []
end
end
class CallbackCancellationDeveloper < ActiveRecord::Base class CallbackCancellationDeveloper < ActiveRecord::Base
self.table_name = 'developers' self.table_name = 'developers'
@ -285,6 +311,17 @@ class CallbacksTest < ActiveRecord::TestCase
], david.history ], david.history
end end
def test_validate_on_contextual_create
david = ContextualCallbacksDeveloper.create('name' => 'David', 'salary' => 1000000)
assert_equal [
:before_validation,
:before_validation_on_create,
:validate,
:after_validation,
:after_validation_on_create
], david.history
end
def test_update def test_update
david = CallbackDeveloper.find(1) david = CallbackDeveloper.find(1)
david.save david.save
@ -344,6 +381,18 @@ class CallbacksTest < ActiveRecord::TestCase
], david.history ], david.history
end end
def test_validate_on_contextual_update
david = ContextualCallbacksDeveloper.find(1)
david.save
assert_equal [
:before_validation,
:before_validation_on_update,
:validate,
:after_validation,
:after_validation_on_update
], david.history
end
def test_destroy def test_destroy
david = CallbackDeveloper.find(1) david = CallbackDeveloper.find(1)
david.destroy david.destroy