提交 de048b10 编写于 作者: R Rick Olson

Improve associations performance by using symbol callbacks instead of string...

Improve associations performance by using symbol callbacks instead of string callbacks. Closes #11108 [adymo]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8867 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 8a2266c0
*SVN* *SVN*
* Improve associations performance by using symbol callbacks instead of string callbacks. #11108 [adymo]
* Improve associations performance by avoiding named block arguments. #11109 [adymo] * Improve associations performance by avoiding named block arguments. #11109 [adymo]
* Introduce the :readonly option to all associations. Records from the association cannot be saved. #11084 [miloops] * Introduce the :readonly option to all associations. Records from the association cannot be saved. #11084 [miloops]
......
...@@ -751,16 +751,16 @@ def has_one(association_id, options = {}) ...@@ -751,16 +751,16 @@ def has_one(association_id, options = {})
ivar = "@#{reflection.name}" ivar = "@#{reflection.name}"
module_eval do method_name = "has_one_after_save_for_#{reflection.name}".to_sym
after_save <<-EOF define_method(method_name) do
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")
if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id) if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id)
association["#{reflection.primary_key_name}"] = id association["#{reflection.primary_key_name}"] = id
association.save(true) association.save(true)
end end
EOF
end end
after_save method_name
association_accessor_methods(reflection, HasOneAssociation) association_accessor_methods(reflection, HasOneAssociation)
association_constructor_method(:build, reflection, HasOneAssociation) association_constructor_method(:build, reflection, HasOneAssociation)
...@@ -832,8 +832,8 @@ def belongs_to(association_id, options = {}) ...@@ -832,8 +832,8 @@ def belongs_to(association_id, options = {})
if reflection.options[:polymorphic] if reflection.options[:polymorphic]
association_accessor_methods(reflection, BelongsToPolymorphicAssociation) association_accessor_methods(reflection, BelongsToPolymorphicAssociation)
module_eval do method_name = "polymorphic_belongs_to_before_save_for_#{reflection.name}".to_sym
before_save <<-EOF define_method(method_name) do
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")
if association && association.target if association && association.target
...@@ -846,15 +846,15 @@ def belongs_to(association_id, options = {}) ...@@ -846,15 +846,15 @@ def belongs_to(association_id, options = {})
self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s
end end
end end
EOF
end end
before_save method_name
else else
association_accessor_methods(reflection, BelongsToAssociation) association_accessor_methods(reflection, BelongsToAssociation)
association_constructor_method(:build, reflection, BelongsToAssociation) association_constructor_method(:build, reflection, BelongsToAssociation)
association_constructor_method(:create, reflection, BelongsToAssociation) association_constructor_method(:create, reflection, BelongsToAssociation)
module_eval do method_name = "belongs_to_before_save_for_#{reflection.name}".to_sym
before_save <<-EOF define_method(method_name) do
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")
if !association.nil? if !association.nil?
...@@ -866,8 +866,8 @@ def belongs_to(association_id, options = {}) ...@@ -866,8 +866,8 @@ def belongs_to(association_id, options = {})
self["#{reflection.primary_key_name}"] = association.id self["#{reflection.primary_key_name}"] = association.id
end end
end end
EOF
end end
before_save method_name
end end
# Create the callbacks to update counter cache # Create the callbacks to update counter cache
...@@ -876,15 +876,19 @@ def belongs_to(association_id, options = {}) ...@@ -876,15 +876,19 @@ def belongs_to(association_id, options = {})
"#{self.to_s.underscore.pluralize}_count" : "#{self.to_s.underscore.pluralize}_count" :
options[:counter_cache] options[:counter_cache]
module_eval( method_name = "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym
"after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + define_method(method_name) do
" unless #{reflection.name}.nil?'" association = send("#{reflection.name}")
) association.class.increment_counter("#{cache_column}", send("#{reflection.primary_key_name}")) unless association.nil?
end
after_create method_name
module_eval( method_name = "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym
"before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + define_method(method_name) do
" unless #{reflection.name}.nil?'" association = send("#{reflection.name}")
) association.class.decrement_counter("#{cache_column}", send("#{reflection.primary_key_name}")) unless association.nil?
end
before_destroy method_name
module_eval( module_eval(
"#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)" "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)"
...@@ -1125,9 +1129,16 @@ def add_multiple_associated_save_callbacks(association_name) ...@@ -1125,9 +1129,16 @@ def add_multiple_associated_save_callbacks(association_name)
end end
validate method_name validate method_name
before_save("@new_record_before_save = new_record?; true")
after_callback = <<-end_eval method_name = "before_save_associated_records_for_#{association_name}".to_sym
define_method(method_name) do
@new_record_before_save = new_record?
true
end
before_save method_name
method_name = "after_create_or_update_associated_records_for_#{association_name}".to_sym
define_method(method_name) do
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")
records_to_save = if @new_record_before_save records_to_save = if @new_record_before_save
...@@ -1144,11 +1155,11 @@ def add_multiple_associated_save_callbacks(association_name) ...@@ -1144,11 +1155,11 @@ def add_multiple_associated_save_callbacks(association_name)
# reconstruct the SQL queries now that we know the owner's id # reconstruct the SQL queries now that we know the owner's id
association.send(:construct_sql) if association.respond_to?(:construct_sql) association.send(:construct_sql) if association.respond_to?(:construct_sql)
end_eval end
# Doesn't use after_save as that would save associations added in after_create/after_update twice # Doesn't use after_save as that would save associations added in after_create/after_update twice
after_create(after_callback) after_create method_name
after_update(after_callback) after_update method_name
end end
def association_constructor_method(constructor, reflection, association_proxy_class) def association_constructor_method(constructor, reflection, association_proxy_class)
...@@ -1194,7 +1205,11 @@ def configure_dependency_for_has_many(reflection) ...@@ -1194,7 +1205,11 @@ def configure_dependency_for_has_many(reflection)
case reflection.options[:dependent] case reflection.options[:dependent]
when :destroy when :destroy
module_eval "before_destroy '#{reflection.name}.each { |o| o.destroy }'" method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym
define_method(method_name) do
send("#{reflection.name}").each { |o| o.destroy }
end
before_destroy method_name
when :delete_all when :delete_all
module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }"
when :nullify when :nullify
...@@ -1209,11 +1224,26 @@ def configure_dependency_for_has_one(reflection) ...@@ -1209,11 +1224,26 @@ def configure_dependency_for_has_one(reflection)
if reflection.options.include?(:dependent) if reflection.options.include?(:dependent)
case reflection.options[:dependent] case reflection.options[:dependent]
when :destroy when :destroy
module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" method_name = "has_one_dependent_destroy_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send("#{reflection.name}")
association.destroy unless association.nil?
end
before_destroy method_name
when :delete when :delete
module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'" method_name = "has_one_dependent_delete_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send("#{reflection.name}")
association.class.delete(association.id) unless association.nil?
end
before_destroy method_name
when :nullify when :nullify
module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil) unless #{reflection.name}.nil?'" method_name = "has_one_dependent_nullify_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send("#{reflection.name}")
association.update_attribute("#{reflection.primary_key_name}", nil) unless association.nil?
end
before_destroy method_name
else else
raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})" raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})"
end end
...@@ -1224,9 +1254,19 @@ def configure_dependency_for_belongs_to(reflection) ...@@ -1224,9 +1254,19 @@ def configure_dependency_for_belongs_to(reflection)
if reflection.options.include?(:dependent) if reflection.options.include?(:dependent)
case reflection.options[:dependent] case reflection.options[:dependent]
when :destroy when :destroy
module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" method_name = "belongs_to_dependent_destroy_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send("#{reflection.name}")
association.destroy unless association.nil?
end
before_destroy method_name
when :delete when :delete
module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'" method_name = "belongs_to_dependent_delete_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send("#{reflection.name}")
association.class.delete(association.id) unless association.nil?
end
before_destroy method_name
else else
raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})" raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
end end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册