mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
823554eafe
Added replace to associations, so you can do project.manager.replace(new_manager) or project.milestones.replace(new_milestones) #402 [Tim Bates] Added build and create methods to has_one and belongs_to associations, so you can now do project.manager.build(attributes) #402 [Tim Bates] Fixed that Base#== wouldn't work for multiple references to the same unsaved object #402 [Tim Bates] Added that if a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last. #402 [Tim Bates] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@417 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
246 lines
8.9 KiB
Ruby
246 lines
8.9 KiB
Ruby
require 'abstract_unit'
|
|
|
|
class CallbackDeveloper < ActiveRecord::Base
|
|
class << self
|
|
def table_name; 'developers' end
|
|
|
|
def callback_string(callback_method)
|
|
"history << [#{callback_method.to_sym.inspect}, :string]"
|
|
end
|
|
|
|
def callback_proc(callback_method)
|
|
Proc.new { |model| model.history << [callback_method, :proc] }
|
|
end
|
|
|
|
def define_callback_method(callback_method)
|
|
define_method("#{callback_method}_method") do |model|
|
|
model.history << [callback_method, :method]
|
|
end
|
|
end
|
|
|
|
def callback_object(callback_method)
|
|
klass = Class.new
|
|
klass.send(:define_method, callback_method) do |model|
|
|
model.history << [callback_method, :object]
|
|
end
|
|
klass.new
|
|
end
|
|
end
|
|
|
|
ActiveRecord::Callbacks::CALLBACKS.each do |callback_method|
|
|
callback_method_sym = callback_method.to_sym
|
|
define_callback_method(callback_method_sym)
|
|
send(callback_method, callback_method_sym)
|
|
send(callback_method, callback_string(callback_method_sym))
|
|
send(callback_method, callback_proc(callback_method_sym))
|
|
send(callback_method, callback_object(callback_method_sym))
|
|
send(callback_method) { |model| model.history << [callback_method_sym, :block] }
|
|
end
|
|
|
|
def history
|
|
@history ||= []
|
|
end
|
|
|
|
# after_initialize and after_find may not be declared using class methods.
|
|
# They are invoked only if instance methods have been defined.
|
|
def after_initialize
|
|
history << [:after_initialize, :method]
|
|
end
|
|
|
|
def after_find
|
|
history << [:after_find, :method]
|
|
end
|
|
end
|
|
|
|
|
|
class CallbacksTest < Test::Unit::TestCase
|
|
def setup
|
|
@developers = create_fixtures('developers')
|
|
end
|
|
|
|
def test_initialize
|
|
david = CallbackDeveloper.new
|
|
assert_equal [
|
|
[ :after_initialize, :method ]
|
|
], david.history
|
|
end
|
|
|
|
def test_find
|
|
david = CallbackDeveloper.find(1)
|
|
assert_equal [
|
|
[ :after_find, :method ],
|
|
[ :after_initialize, :method ]
|
|
], david.history
|
|
end
|
|
|
|
def test_new_valid?
|
|
david = CallbackDeveloper.new
|
|
david.valid?
|
|
assert_equal [
|
|
[ :after_initialize, :method ],
|
|
[ :before_validation, :string ],
|
|
[ :before_validation, :proc ],
|
|
[ :before_validation, :object ],
|
|
[ :before_validation, :block ],
|
|
[ :before_validation_on_create, :string ],
|
|
[ :before_validation_on_create, :proc ],
|
|
[ :before_validation_on_create, :object ],
|
|
[ :before_validation_on_create, :block ],
|
|
[ :after_validation, :string ],
|
|
[ :after_validation, :proc ],
|
|
[ :after_validation, :object ],
|
|
[ :after_validation, :block ],
|
|
[ :after_validation_on_create, :string ],
|
|
[ :after_validation_on_create, :proc ],
|
|
[ :after_validation_on_create, :object ],
|
|
[ :after_validation_on_create, :block ]
|
|
], david.history
|
|
end
|
|
|
|
def test_existing_valid?
|
|
david = CallbackDeveloper.find(1)
|
|
david.valid?
|
|
assert_equal [
|
|
[ :after_find, :method ],
|
|
[ :after_initialize, :method ],
|
|
[ :before_validation, :string ],
|
|
[ :before_validation, :proc ],
|
|
[ :before_validation, :object ],
|
|
[ :before_validation, :block ],
|
|
[ :before_validation_on_update, :string ],
|
|
[ :before_validation_on_update, :proc ],
|
|
[ :before_validation_on_update, :object ],
|
|
[ :before_validation_on_update, :block ],
|
|
[ :after_validation, :string ],
|
|
[ :after_validation, :proc ],
|
|
[ :after_validation, :object ],
|
|
[ :after_validation, :block ],
|
|
[ :after_validation_on_update, :string ],
|
|
[ :after_validation_on_update, :proc ],
|
|
[ :after_validation_on_update, :object ],
|
|
[ :after_validation_on_update, :block ]
|
|
], david.history
|
|
end
|
|
|
|
def test_create
|
|
david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000)
|
|
assert_equal [
|
|
[ :after_initialize, :method ],
|
|
[ :before_validation, :string ],
|
|
[ :before_validation, :proc ],
|
|
[ :before_validation, :object ],
|
|
[ :before_validation, :block ],
|
|
[ :before_validation_on_create, :string ],
|
|
[ :before_validation_on_create, :proc ],
|
|
[ :before_validation_on_create, :object ],
|
|
[ :before_validation_on_create, :block ],
|
|
[ :after_validation, :string ],
|
|
[ :after_validation, :proc ],
|
|
[ :after_validation, :object ],
|
|
[ :after_validation, :block ],
|
|
[ :after_validation_on_create, :string ],
|
|
[ :after_validation_on_create, :proc ],
|
|
[ :after_validation_on_create, :object ],
|
|
[ :after_validation_on_create, :block ],
|
|
[ :before_save, :string ],
|
|
[ :before_save, :proc ],
|
|
[ :before_save, :object ],
|
|
[ :before_save, :block ],
|
|
[ :before_create, :string ],
|
|
[ :before_create, :proc ],
|
|
[ :before_create, :object ],
|
|
[ :before_create, :block ],
|
|
[ :after_create, :string ],
|
|
[ :after_create, :proc ],
|
|
[ :after_create, :object ],
|
|
[ :after_create, :block ],
|
|
[ :after_save, :string ],
|
|
[ :after_save, :proc ],
|
|
[ :after_save, :object ],
|
|
[ :after_save, :block ]
|
|
], david.history
|
|
end
|
|
|
|
def test_save
|
|
david = CallbackDeveloper.find(1)
|
|
david.save
|
|
assert_equal [
|
|
[ :after_find, :method ],
|
|
[ :after_initialize, :method ],
|
|
[ :before_validation, :string ],
|
|
[ :before_validation, :proc ],
|
|
[ :before_validation, :object ],
|
|
[ :before_validation, :block ],
|
|
[ :before_validation_on_update, :string ],
|
|
[ :before_validation_on_update, :proc ],
|
|
[ :before_validation_on_update, :object ],
|
|
[ :before_validation_on_update, :block ],
|
|
[ :after_validation, :string ],
|
|
[ :after_validation, :proc ],
|
|
[ :after_validation, :object ],
|
|
[ :after_validation, :block ],
|
|
[ :after_validation_on_update, :string ],
|
|
[ :after_validation_on_update, :proc ],
|
|
[ :after_validation_on_update, :object ],
|
|
[ :after_validation_on_update, :block ],
|
|
[ :before_save, :string ],
|
|
[ :before_save, :proc ],
|
|
[ :before_save, :object ],
|
|
[ :before_save, :block ],
|
|
[ :before_update, :string ],
|
|
[ :before_update, :proc ],
|
|
[ :before_update, :object ],
|
|
[ :before_update, :block ],
|
|
[ :after_update, :string ],
|
|
[ :after_update, :proc ],
|
|
[ :after_update, :object ],
|
|
[ :after_update, :block ],
|
|
[ :after_save, :string ],
|
|
[ :after_save, :proc ],
|
|
[ :after_save, :object ],
|
|
[ :after_save, :block ]
|
|
], david.history
|
|
end
|
|
|
|
def test_destroy
|
|
david = CallbackDeveloper.find(1)
|
|
david.destroy
|
|
assert_equal [
|
|
[ :after_find, :method ],
|
|
[ :after_initialize, :method ],
|
|
[ :before_destroy, :string ],
|
|
[ :before_destroy, :proc ],
|
|
[ :before_destroy, :object ],
|
|
[ :before_destroy, :block ],
|
|
[ :after_destroy, :string ],
|
|
[ :after_destroy, :proc ],
|
|
[ :after_destroy, :object ],
|
|
[ :after_destroy, :block ]
|
|
], david.history
|
|
end
|
|
|
|
def test_delete
|
|
david = CallbackDeveloper.find(1)
|
|
CallbackDeveloper.delete(david.id)
|
|
assert_equal [
|
|
[ :after_find, :method ],
|
|
[ :after_initialize, :method ]
|
|
], david.history
|
|
end
|
|
|
|
def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
|
|
david = CallbackDeveloper.find(1)
|
|
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
|
|
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
|
|
david.save
|
|
assert_equal [
|
|
[ :after_find, :method ],
|
|
[ :after_initialize, :method ],
|
|
[ :before_validation, :string ],
|
|
[ :before_validation, :proc ],
|
|
[ :before_validation, :object ],
|
|
[ :before_validation, :block ],
|
|
[ :before_validation, :returning_false ]
|
|
], david.history
|
|
end
|
|
end
|