# File lib/active_record/associations.rb, line 640
      def has_and_belongs_to_many(association_id, options = {}, &extension)
        options.assert_valid_keys(
          :class_name, :table_name, :foreign_key, :association_foreign_key, :conditions, :include,
          :join_table, :finder_sql, :delete_sql, :insert_sql, :order, :uniq, :before_add, :after_add, 
          :before_remove, :after_remove, :extend
        )

        options[:extend] = create_extension_module(association_id, extension) if block_given?

        association_name, association_class_name, association_class_primary_key_name =
              associate_identification(association_id, options[:class_name], options[:foreign_key])

        require_association_class(association_class_name)

        options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(association_class_name))

        add_multiple_associated_save_callbacks(association_name)
      
        collection_accessor_methods(association_name, association_class_name, association_class_primary_key_name, options, HasAndBelongsToManyAssociation)

        # Don't use a before_destroy callback since users' before_destroy
        # callbacks will be executed after the association is wiped out.
        old_method = "destroy_without_habtm_shim_for_#{association_name}"
        class_eval "alias_method :\#{old_method}, :destroy_without_callbacks\ndef destroy_without_callbacks\n\#{association_name}.clear\n\#{old_method}\nend\n"

        add_association_callbacks(association_name, options)
        
        # deprecated api
        deprecated_collection_count_method(association_name)
        deprecated_add_association_relation(association_name)
        deprecated_remove_association_relation(association_name)
        deprecated_has_collection_method(association_name)
      end