Merge pull request #17093 from phiggins/remove-dynamic-send-on-built-in-callbacks

Reduce allocations when running AR callbacks.
This commit is contained in:
Aaron Patterson 2014-09-29 12:34:53 -07:00
commit a455e3f4e9
8 changed files with 31 additions and 22 deletions

@ -390,7 +390,7 @@ def invalid?(context = nil)
protected
def run_validations! #:nodoc:
run_callbacks :validate
run_validate_callbacks
errors.empty?
end
end

@ -108,7 +108,7 @@ def after_validation(*args, &block)
# Overwrite run validations to include callbacks.
def run_validations! #:nodoc:
run_callbacks(:validation) { super }
run_validation_callbacks { super }
end
end
end

@ -159,7 +159,7 @@ def delete_records(records, method)
count = scope.destroy_all.length
else
scope.to_a.each do |record|
record.run_callbacks :destroy
record.run_destroy_callbacks
end
arel = scope.arel

@ -289,25 +289,25 @@ module ClassMethods
end
def destroy #:nodoc:
run_callbacks(:destroy) { super }
run_destroy_callbacks { super }
end
def touch(*) #:nodoc:
run_callbacks(:touch) { super }
run_touch_callbacks { super }
end
private
def create_or_update #:nodoc:
run_callbacks(:save) { super }
run_save_callbacks { super }
end
def _create_record #:nodoc:
run_callbacks(:create) { super }
run_create_callbacks { super }
end
def _update_record(*) #:nodoc:
run_callbacks(:update) { super }
run_update_callbacks { super }
end
end
end

@ -360,7 +360,7 @@ def checkin(conn)
synchronize do
owner = conn.owner
conn.run_callbacks :checkin do
conn.run_checkin_callbacks do
conn.expire
end
@ -449,7 +449,7 @@ def checkout_new_connection
end
def checkout_and_verify(c)
c.run_callbacks :checkout do
c.run_checkout_callbacks do
c.verify!
end
c

@ -272,7 +272,7 @@ def initialize(attributes = nil, options = {})
init_attributes(attributes, options) if attributes
yield self if block_given?
run_callbacks :initialize unless _initialize_callbacks.empty?
run_initialize_callbacks
end
# Initialize an empty model object from +coder+. +coder+ must contain
@ -294,8 +294,8 @@ def init_with(coder)
self.class.define_attribute_methods
run_callbacks :find
run_callbacks :initialize
run_find_callbacks
run_initialize_callbacks
self
end
@ -331,7 +331,7 @@ def initialize_dup(other) # :nodoc:
@attributes = @attributes.dup
@attributes.reset(self.class.primary_key)
run_callbacks(:initialize) unless _initialize_callbacks.empty?
run_initialize_callbacks
@aggregation_cache = {}
@association_cache = {}

@ -309,7 +309,7 @@ def rollback_active_record_state!
# Ensure that it is not called if the object was never persisted (failed create),
# but call it after the commit of a destroyed object.
def committed!(should_run_callbacks = true) #:nodoc:
run_callbacks :commit if should_run_callbacks && destroyed? || persisted?
run_commit_callbacks if should_run_callbacks && destroyed? || persisted?
ensure
force_clear_transaction_record_state
end
@ -317,7 +317,7 @@ def committed!(should_run_callbacks = true) #:nodoc:
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
# state should be rolled back to the beginning or just to the last savepoint.
def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
run_callbacks :rollback if should_run_callbacks
run_rollback_callbacks if should_run_callbacks
ensure
restore_transaction_record_state(force_restore_state)
clear_transaction_record_state

@ -78,18 +78,21 @@ module Callbacks
# save
# end
def run_callbacks(kind, &block)
cbs = send("_#{kind}_callbacks")
if cbs.empty?
yield if block_given?
send "run_#{kind}_callbacks", &block
end
private
def _run_callbacks(callbacks, &block)
if callbacks.empty?
block.call if block
else
runner = cbs.compile
runner = callbacks.compile
e = Filters::Environment.new(self, false, nil, block)
runner.call(e).value
end
end
private
# A hook invoked every time a before callback is halted.
# This can be overridden in AS::Callback implementors in order
# to provide better debugging/logging.
@ -722,6 +725,12 @@ def define_callbacks(*names)
names.each do |name|
class_attribute "_#{name}_callbacks"
set_callbacks name, CallbackChain.new(name, options)
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def run_#{name}_callbacks(&block)
_run_callbacks(_#{name}_callbacks, &block)
end
RUBY
end
end