diff options
Diffstat (limited to 'activesupport/test/callbacks_test.rb')
-rw-r--r-- | activesupport/test/callbacks_test.rb | 167 |
1 files changed, 116 insertions, 51 deletions
diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb index a624473f46..783952c8c7 100644 --- a/activesupport/test/callbacks_test.rb +++ b/activesupport/test/callbacks_test.rb @@ -1,4 +1,4 @@ -require 'abstract_unit' +require "abstract_unit" module CallbacksTest class Record @@ -56,27 +56,31 @@ module CallbacksTest end class Person < Record + attr_accessor :save_fails + [:before_save, :after_save].each do |callback_method| callback_method_sym = callback_method.to_sym send(callback_method, callback_symbol(callback_method_sym)) ActiveSupport::Deprecation.silence { send(callback_method, callback_string(callback_method_sym)) } send(callback_method, callback_proc(callback_method_sym)) - send(callback_method, callback_object(callback_method_sym.to_s.gsub(/_save/, ''))) + send(callback_method, callback_object(callback_method_sym.to_s.gsub(/_save/, ""))) send(callback_method, CallbackClass) send(callback_method) { |model| model.history << [callback_method_sym, :block] } end def save - run_callbacks :save + run_callbacks :save do + raise "inside save" if save_fails + end end end class PersonSkipper < Person - skip_callback :save, :before, :before_save_method, :if => :yes - skip_callback :save, :after, :after_save_method, :unless => :yes - skip_callback :save, :after, :after_save_method, :if => :no - skip_callback :save, :before, :before_save_method, :unless => :no - skip_callback :save, :before, CallbackClass , :if => :yes + skip_callback :save, :before, :before_save_method, if: :yes + skip_callback :save, :after, :after_save_method, unless: :yes + skip_callback :save, :after, :after_save_method, if: :no + skip_callback :save, :before, :before_save_method, unless: :no + skip_callback :save, :before, CallbackClass , if: :yes def yes; true; end def no; false; end end @@ -89,7 +93,7 @@ module CallbacksTest define_callbacks :dispatch - set_callback :dispatch, :before, :log, :unless => proc {|c| c.action_name == :index || c.action_name == :show } + set_callback :dispatch, :before, :log, unless: proc { |c| c.action_name == :index || c.action_name == :show } set_callback :dispatch, :after, :log2 attr_reader :action_name, :logger @@ -114,7 +118,7 @@ module CallbacksTest end class Child < ParentController - skip_callback :dispatch, :before, :log, :if => proc {|c| c.action_name == :update} + skip_callback :dispatch, :before, :log, if: proc { |c| c.action_name == :update } skip_callback :dispatch, :after, :log2 end @@ -125,10 +129,10 @@ module CallbacksTest super end - before_save Proc.new {|r| r.history << [:before_save, :starts_true, :if] }, :if => :starts_true - before_save Proc.new {|r| r.history << [:before_save, :starts_false, :if] }, :if => :starts_false - before_save Proc.new {|r| r.history << [:before_save, :starts_true, :unless] }, :unless => :starts_true - before_save Proc.new {|r| r.history << [:before_save, :starts_false, :unless] }, :unless => :starts_false + before_save Proc.new { |r| r.history << [:before_save, :starts_true, :if] }, if: :starts_true + before_save Proc.new { |r| r.history << [:before_save, :starts_false, :if] }, if: :starts_false + before_save Proc.new { |r| r.history << [:before_save, :starts_true, :unless] }, unless: :starts_true + before_save Proc.new { |r| r.history << [:before_save, :starts_false, :unless] }, unless: :starts_false def starts_true if @@starts_true @@ -181,27 +185,25 @@ module CallbacksTest end end - - class ConditionalPerson < Record # proc - before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true } - before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false } - before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false } - before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true } + before_save Proc.new { |r| r.history << [:before_save, :proc] }, if: Proc.new { |r| true } + before_save Proc.new { |r| r.history << "b00m" }, if: Proc.new { |r| false } + before_save Proc.new { |r| r.history << [:before_save, :proc] }, unless: Proc.new { |r| false } + before_save Proc.new { |r| r.history << "b00m" }, unless: Proc.new { |r| true } # symbol - before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes - before_save Proc.new { |r| r.history << "b00m" }, :if => :no - before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no - before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, if: :yes + before_save Proc.new { |r| r.history << "b00m" }, if: :no + before_save Proc.new { |r| r.history << [:before_save, :symbol] }, unless: :no + before_save Proc.new { |r| r.history << "b00m" }, unless: :yes # string - before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes' - before_save Proc.new { |r| r.history << "b00m" }, :if => 'no' - before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no' - before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes' + before_save Proc.new { |r| r.history << [:before_save, :string] }, if: "yes" + before_save Proc.new { |r| r.history << "b00m" }, if: "no" + before_save Proc.new { |r| r.history << [:before_save, :string] }, unless: "no" + before_save Proc.new { |r| r.history << "b00m" }, unless: "yes" # Combined if and unless - before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no - before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes + before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, if: :yes, unless: :no + before_save Proc.new { |r| r.history << "b00m" }, if: :yes, unless: :yes def yes; true; end def other_yes; true; end @@ -224,19 +226,20 @@ module CallbacksTest class AroundPerson < MySuper attr_reader :history + attr_accessor :save_fails - set_callback :save, :before, :nope, :if => :no - set_callback :save, :before, :nope, :unless => :yes + set_callback :save, :before, :nope, if: :no + set_callback :save, :before, :nope, unless: :yes set_callback :save, :after, :tweedle ActiveSupport::Deprecation.silence { set_callback :save, :before, "tweedle_dee" } - set_callback :save, :before, proc {|m| m.history << "yup" } - set_callback :save, :before, :nope, :if => proc { false } - set_callback :save, :before, :nope, :unless => proc { true } - set_callback :save, :before, :yup, :if => proc { true } - set_callback :save, :before, :yup, :unless => proc { false } + set_callback :save, :before, proc { |m| m.history << "yup" } + set_callback :save, :before, :nope, if: proc { false } + set_callback :save, :before, :nope, unless: proc { true } + set_callback :save, :before, :yup, if: proc { true } + set_callback :save, :before, :yup, unless: proc { false } set_callback :save, :around, :tweedle_dum - set_callback :save, :around, :w0tyes, :if => :yes - set_callback :save, :around, :w0tno, :if => :no + set_callback :save, :around, :w0tyes, if: :yes + set_callback :save, :around, :w0tno, if: :no set_callback :save, :around, :tweedle_deedle def no; false; end @@ -287,6 +290,7 @@ module CallbacksTest def save run_callbacks :save do + raise "inside save" if save_fails @history << "running" end end @@ -323,7 +327,7 @@ module CallbacksTest define_callbacks :save attr_reader :stuff - set_callback :save, :before, :action, :if => :yes + set_callback :save, :before, :action, if: :yes def yes() true end @@ -361,7 +365,6 @@ module CallbacksTest end class ExtendCallbacks - include ActiveSupport::Callbacks define_callbacks :save @@ -405,6 +408,71 @@ module CallbacksTest end end + class CallStackTest < ActiveSupport::TestCase + def test_tidy_call_stack + around = AroundPerson.new + around.save_fails = true + + exception = (around.save rescue $!) + + # Make sure we have the exception we're expecting + assert_equal "inside save", exception.message + + call_stack = exception.backtrace_locations + call_stack.pop caller_locations(0).size + + # Yes, this looks like an implementation test, but it's the least + # obtuse way of asserting that there aren't a load of entries in + # the call stack for each callback. + # + # If you've renamed a method, or squeezed more lines out, go ahead + # and update this assertion. But if you're here because a + # refactoring added new lines, please reconsider. + + # As shown here, our current budget is one line for run_callbacks + # itself, plus N+1 lines where N is the number of :around + # callbacks that have been invoked, if there are any (plus + # whatever the callbacks do themselves, of course). + + assert_equal [ + "block in save", + "block in run_callbacks", + "tweedle_deedle", + "block in run_callbacks", + "w0tyes", + "block in run_callbacks", + "tweedle_dum", + "block in run_callbacks", + ("call" if RUBY_VERSION < "2.3"), + "run_callbacks", + "save" + ].compact, call_stack.map(&:label) + end + + def test_short_call_stack + person = Person.new + person.save_fails = true + + exception = (person.save rescue $!) + + # Make sure we have the exception we're expecting + assert_equal "inside save", exception.message + + call_stack = exception.backtrace_locations + call_stack.pop caller_locations(0).size + + # This budget much simpler: with no :around callbacks invoked, + # there should be just one line. run_callbacks yields directly + # back to its caller. + + assert_equal [ + "block in save", + "run_callbacks", + "save" + ], call_stack.map(&:label) + end + end + class AroundCallbackResultTest < ActiveSupport::TestCase def test_save_around around = AroundPersonResult.new @@ -453,7 +521,6 @@ module CallbacksTest end class CallbacksTest < ActiveSupport::TestCase - def test_save_person person = Person.new assert_equal [], person.history @@ -491,8 +558,6 @@ module CallbacksTest end end - - class ResetCallbackTest < ActiveSupport::TestCase def test_save_conditional_person person = CleanPerson.new @@ -637,7 +702,7 @@ module CallbacksTest class CustomScopeObject include ActiveSupport::Callbacks - define_callbacks :save, :scope => [:kind, :name] + define_callbacks :save, scope: [:kind, :name] set_callback :save, :before, CallbackObject.new attr_accessor :record @@ -810,7 +875,7 @@ module CallbacksTest class WriterSkipper < Person attr_accessor :age - skip_callback :save, :before, :before_save_method, :if => lambda {self.age > 21} + skip_callback :save, :before, :before_save_method, if: -> { age > 21 } end class WriterCallbacksTest < ActiveSupport::TestCase @@ -885,7 +950,7 @@ module CallbacksTest def test_proc_arity_2 assert_raises(ArgumentError) do - klass = build_class(->(x,y) { }) + klass = build_class(->(x,y) {}) klass.new.run end end @@ -903,7 +968,7 @@ module CallbacksTest Class.new { include ActiveSupport::Callbacks define_callbacks :foo - set_callback :foo, :before, :foo, :if => callback + set_callback :foo, :before, :foo, if: callback def foo; end def run; run_callbacks :foo; end } @@ -918,8 +983,8 @@ module CallbacksTest } klass = Class.new { include ActiveSupport::Callbacks - define_callbacks :foo, :scope => [:name] - set_callback :foo, :before, :foo, :if => callback + define_callbacks :foo, scope: [:name] + set_callback :foo, :before, :foo, if: callback def run; run_callbacks :foo; end private def foo; end @@ -964,7 +1029,7 @@ module CallbacksTest def test_proc_arity2 assert_raises(ArgumentError) do - object = build_class(->(a,b) { }).new + object = build_class(->(a,b) {}).new object.run end end |