require File.join(File.dirname(__FILE__),"..","helper") class User < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary end class CallbackDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary class << self 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 ActiveObject::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 are invoked only if instance methods have been defined. def after_initialize end def after_find end end class ParentDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary attr_accessor :after_save_called before_validation {|record| record.after_save_called = true} end class ChildDeveloper < ParentDeveloper primary_key :email attribute :name,:email,:password,:salary end class RecursiveCallbackDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary before_save :on_before_save after_save :on_after_save attr_reader :on_before_save_called, :on_after_save_called def on_before_save @on_before_save_called ||= 0 @on_before_save_called += 1 save unless @on_before_save_called > 1 end def on_after_save @on_after_save_called ||= 0 @on_after_save_called += 1 save unless @on_after_save_called > 1 end end class ImmutableDestroyDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary validates_inclusion_of :salary, :in => 50000..200000 before_destroy :cancel def cancelled? @cancelled == true end private def cancel @cancelled = true false end end class ImmutableSaveDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary validates_inclusion_of :salary, :in => 50000..200000 before_save :cancel def cancelled? @cancelled == true end private def cancel @cancelled = true false end end class ImmutableMethodDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary validates_inclusion_of :salary, :in => 50000..200000 def cancelled? @cancelled == true end def before_save @cancelled = true false end def before_destroy @cancelled = true false end end class CallbackCancellationDeveloper < ActiveObject::Base primary_key :email attribute :name,:email,:password,:salary def before_create false end end class CallbacksTest < Test::Unit::TestCase def setup @attributes={:name=>'aaron',:email=>'aaron@nonobo.com',:password=>'123456',:salary=>100000} end def test_initialize david = CallbackDeveloper.new assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], ], david.history end def test_find CallbackDeveloper.create(@attributes) david = CallbackDeveloper.find(@attributes[:email]) assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], ], david.history david.destroy end def test_new_valid? david = CallbackDeveloper.new david.valid? assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], [ :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? CallbackDeveloper.create(@attributes) david = CallbackDeveloper.find(@attributes[:email]) david.valid? assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], [ :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 david.destroy end def test_create david = CallbackDeveloper.create(@attributes) assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], [ :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 david.destroy end def test_save CallbackDeveloper.create(@attributes) david = CallbackDeveloper.find(@attributes[:email]) david.save assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], [ :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 david.destroy end def test_destroy CallbackDeveloper.create(@attributes) david = CallbackDeveloper.find(@attributes[:email]) david.destroy assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], [ :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 CallbackDeveloper.create(@attributes) david = CallbackDeveloper.find(@attributes[:email]) CallbackDeveloper.delete(david.id) assert_equal [ [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], ], david.history end def test_before_save_returning_false david = ImmutableSaveDeveloper.create(@attributes) assert david.valid? assert !david.save assert_raises(ActiveObject::ObjectNotSaved) { david.save! } david.salary = 10_000_000 assert !david.valid? assert !david.save assert_raises(ActiveObject::ObjectInvalid) { david.save! } end def test_before_create_returning_false someone = CallbackCancellationDeveloper.new assert someone.valid? assert !someone.save end def test_before_destroy_returning_false david = ImmutableDestroyDeveloper.create(@attributes) assert !david.destroy assert_not_nil ImmutableDestroyDeveloper.find(@attributes[:email]) end def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper CallbackDeveloper.create(@attributes) david = CallbackDeveloper.find(@attributes[:email]) 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_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], [ :before_validation, :returning_false ] ], david.history david.destroy end def test_inheritence_of_callbacks parent = ParentDeveloper.new assert !parent.after_save_called parent.save assert parent.after_save_called child = ChildDeveloper.new assert !child.after_save_called child.save assert child.after_save_called end end