Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 8867

Show
Ignore:
Timestamp:
02/14/08 07:53:37 (1 year ago)
Author:
rick
Message:

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

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r8865 r8867  
    11*SVN* 
     2 
     3* Improve associations performance by using symbol callbacks instead of string callbacks. #11108 [adymo] 
    24 
    35* Improve associations performance by avoiding named block arguments.  #11109 [adymo] 
  • trunk/activerecord/lib/active_record/associations.rb

    r8864 r8867  
    752752        ivar = "@#{reflection.name}" 
    753753 
    754         module_eval do 
    755           after_save <<-EOF 
    756             association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
    757  
    758             if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id) 
    759               association["#{reflection.primary_key_name}"] = id 
    760               association.save(true) 
    761             end 
    762           EOF 
    763         end 
     754        method_name = "has_one_after_save_for_#{reflection.name}".to_sym 
     755        define_method(method_name) do 
     756          association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
     757 
     758          if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id) 
     759            association["#{reflection.primary_key_name}"] = id 
     760            association.save(true) 
     761          end 
     762        end 
     763        after_save method_name 
    764764 
    765765        association_accessor_methods(reflection, HasOneAssociation) 
     
    833833          association_accessor_methods(reflection, BelongsToPolymorphicAssociation) 
    834834 
    835           module_eval do 
    836             before_save <<-EOF 
    837               association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
    838  
    839               if association && association.target 
    840                 if association.new_record? 
    841                   association.save(true) 
    842                 end 
    843  
    844                 if association.updated? 
    845                   self["#{reflection.primary_key_name}"] = association.id 
    846                   self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s 
    847                 end 
    848               end 
    849             EOF 
    850           end 
     835          method_name = "polymorphic_belongs_to_before_save_for_#{reflection.name}".to_sym 
     836          define_method(method_name) do 
     837            association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
     838 
     839            if association && association.target 
     840              if association.new_record? 
     841                association.save(true) 
     842              end 
     843 
     844              if association.updated? 
     845                self["#{reflection.primary_key_name}"] = association.id 
     846                self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s 
     847              end 
     848            end 
     849          end 
     850          before_save method_name 
    851851        else 
    852852          association_accessor_methods(reflection, BelongsToAssociation) 
     
    854854          association_constructor_method(:create, reflection, BelongsToAssociation) 
    855855 
    856           module_eval do 
    857             before_save <<-EOF 
    858               association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
    859  
    860               if !association.nil? 
    861                 if association.new_record? 
    862                   association.save(true) 
    863                 end 
    864  
    865                 if association.updated? 
    866                   self["#{reflection.primary_key_name}"] = association.id 
    867                 end 
    868               end 
    869             EOF 
    870           end 
     856          method_name = "belongs_to_before_save_for_#{reflection.name}".to_sym 
     857          define_method(method_name) do 
     858            association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
     859 
     860            if !association.nil? 
     861              if association.new_record? 
     862                association.save(true) 
     863              end 
     864 
     865              if association.updated? 
     866                self["#{reflection.primary_key_name}"] = association.id 
     867              end 
     868            end 
     869          end 
     870          before_save method_name 
    871871        end 
    872872 
     
    877877            options[:counter_cache] 
    878878 
    879           module_eval( 
    880             "after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + 
    881             " unless #{reflection.name}.nil?'" 
    882           ) 
    883  
    884           module_eval( 
    885             "before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + 
    886             " unless #{reflection.name}.nil?'" 
    887           ) 
     879          method_name = "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym 
     880          define_method(method_name) do 
     881            association = send("#{reflection.name}") 
     882            association.class.increment_counter("#{cache_column}", send("#{reflection.primary_key_name}")) unless association.nil? 
     883          end 
     884          after_create method_name 
     885 
     886          method_name = "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym 
     887          define_method(method_name) do 
     888            association = send("#{reflection.name}") 
     889            association.class.decrement_counter("#{cache_column}", send("#{reflection.primary_key_name}")) unless association.nil? 
     890          end 
     891          before_destroy method_name 
    888892 
    889893          module_eval( 
     
    11261130 
    11271131          validate method_name 
    1128           before_save("@new_record_before_save = new_record?; true") 
    1129  
    1130           after_callback = <<-end_eval 
     1132 
     1133          method_name = "before_save_associated_records_for_#{association_name}".to_sym 
     1134          define_method(method_name) do 
     1135            @new_record_before_save = new_record? 
     1136            true 
     1137          end 
     1138          before_save method_name 
     1139 
     1140          method_name = "after_create_or_update_associated_records_for_#{association_name}".to_sym 
     1141          define_method(method_name) do 
    11311142            association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 
    11321143 
     
    11451156            # reconstruct the SQL queries now that we know the owner's id 
    11461157            association.send(:construct_sql) if association.respond_to?(:construct_sql) 
    1147           end_eval 
     1158          end 
    11481159 
    11491160          # Doesn't use after_save as that would save associations added in after_create/after_update twice 
    1150           after_create(after_callback) 
    1151           after_update(after_callback) 
     1161          after_create method_name 
     1162          after_update method_name 
    11521163        end 
    11531164 
     
    11951206            case reflection.options[:dependent] 
    11961207              when :destroy 
    1197                 module_eval "before_destroy '#{reflection.name}.each { |o| o.destroy }'" 
     1208                method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym 
     1209                define_method(method_name) do 
     1210                  send("#{reflection.name}").each { |o| o.destroy } 
     1211                end 
     1212                before_destroy method_name 
    11981213              when :delete_all 
    11991214                module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" 
     
    12101225            case reflection.options[:dependent] 
    12111226              when :destroy 
    1212                 module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" 
     1227                method_name = "has_one_dependent_destroy_for_#{reflection.name}".to_sym 
     1228                define_method(method_name) do 
     1229                  association = send("#{reflection.name}") 
     1230                  association.destroy unless association.nil? 
     1231                end 
     1232                before_destroy method_name 
    12131233              when :delete 
    1214                 module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'" 
     1234                method_name = "has_one_dependent_delete_for_#{reflection.name}".to_sym 
     1235                define_method(method_name) do 
     1236                  association = send("#{reflection.name}") 
     1237                  association.class.delete(association.id) unless association.nil? 
     1238                end 
     1239                before_destroy method_name 
    12151240              when :nullify 
    1216                 module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil) unless #{reflection.name}.nil?'" 
     1241                method_name = "has_one_dependent_nullify_for_#{reflection.name}".to_sym 
     1242                define_method(method_name) do 
     1243                  association = send("#{reflection.name}") 
     1244                  association.update_attribute("#{reflection.primary_key_name}", nil) unless association.nil? 
     1245                end 
     1246                before_destroy method_name 
    12171247              else 
    12181248                raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})" 
     
    12251255            case reflection.options[:dependent] 
    12261256              when :destroy 
    1227                 module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" 
     1257                method_name = "belongs_to_dependent_destroy_for_#{reflection.name}".to_sym 
     1258                define_method(method_name) do 
     1259                  association = send("#{reflection.name}") 
     1260                  association.destroy unless association.nil? 
     1261                end 
     1262                before_destroy method_name 
    12281263              when :delete 
    1229                 module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'" 
     1264                method_name = "belongs_to_dependent_delete_for_#{reflection.name}".to_sym 
     1265                define_method(method_name) do 
     1266                  association = send("#{reflection.name}") 
     1267                  association.class.delete(association.id) unless association.nil? 
     1268                end 
     1269                before_destroy method_name 
    12301270              else 
    12311271                raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"