Ticket #11108: no_string_callbacks_in_associations.patch
| File no_string_callbacks_in_associations.patch, 10.5 kB (added by adymo, 7 months ago) |
|---|
-
activerecord/lib/active_record/associations.rb
old new 751 751 752 752 ivar = "@#{reflection.name}" 753 753 754 m odule_eval do755 after_save <<-EOF756 association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")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 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 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 763 762 end 763 after_save method_name 764 764 765 765 association_accessor_methods(reflection, HasOneAssociation) 766 766 association_constructor_method(:build, reflection, HasOneAssociation) … … 832 832 if reflection.options[:polymorphic] 833 833 association_accessor_methods(reflection, BelongsToPolymorphicAssociation) 834 834 835 m odule_eval do836 before_save <<-EOF837 association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")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 838 839 if association && association.target840 if association.new_record?841 association.save(true)842 end839 if association && association.target 840 if association.new_record? 841 association.save(true) 842 end 843 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 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 848 847 end 849 EOF848 end 850 849 end 850 before_save method_name 851 851 else 852 852 association_accessor_methods(reflection, BelongsToAssociation) 853 853 association_constructor_method(:build, reflection, BelongsToAssociation) 854 854 association_constructor_method(:create, reflection, BelongsToAssociation) 855 855 856 m odule_eval do857 before_save <<-EOF858 association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}")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 859 860 if !association.nil?861 if association.new_record?862 association.save(true)863 end860 if !association.nil? 861 if association.new_record? 862 association.save(true) 863 end 864 864 865 if association.updated? 866 self["#{reflection.primary_key_name}"] = association.id 867 end 865 if association.updated? 866 self["#{reflection.primary_key_name}"] = association.id 868 867 end 869 EOF868 end 870 869 end 870 before_save method_name 871 871 end 872 872 873 873 # Create the callbacks to update counter cache … … 876 876 "#{self.to_s.underscore.pluralize}_count" : 877 877 options[:counter_cache] 878 878 879 module_eval( 880 "after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + 881 " unless #{reflection.name}.nil?'" 882 ) 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 883 885 884 module_eval( 885 "before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + 886 " unless #{reflection.name}.nil?'" 887 ) 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 888 892 889 893 module_eval( 890 894 "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)" … … 1125 1129 end 1126 1130 1127 1131 validate method_name 1128 before_save("@new_record_before_save = new_record?; true")1129 1132 1130 after_callback = <<-end_eval 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 1131 1142 association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") 1132 1143 1133 1144 records_to_save = if @new_record_before_save … … 1144 1155 1145 1156 # reconstruct the SQL queries now that we know the owner's id 1146 1157 association.send(:construct_sql) if association.respond_to?(:construct_sql) 1147 end _eval1158 end 1148 1159 1149 1160 # 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 1152 1163 end 1153 1164 1154 1165 def association_constructor_method(constructor, reflection, association_proxy_class) … … 1194 1205 1195 1206 case reflection.options[:dependent] 1196 1207 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 1198 1213 when :delete_all 1199 1214 module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" 1200 1215 when :nullify … … 1209 1224 if reflection.options.include?(:dependent) 1210 1225 case reflection.options[:dependent] 1211 1226 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 1213 1233 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 1215 1240 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 1217 1247 else 1218 1248 raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})" 1219 1249 end … … 1224 1254 if reflection.options.include?(:dependent) 1225 1255 case reflection.options[:dependent] 1226 1256 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 1228 1263 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 1230 1270 else 1231 1271 raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})" 1232 1272 end