Search code examples
ruby-on-railsrspecrspec-rails

Clean solution for resetting class variables in between rspec tests


Is there a better way to clean class variables in between Rspec tests than to clear them explicitely from the after(:each) method? I would prefer a way that "clears them all", instead of having to remember adding them to the config.after every time again...

config.after(:each) do
  DatabaseCleaner.clean

  Currency.class_variable_set :@@default, nil
end

Solution

  • I finally implemented this by defining a method in lib/auto_clean_class_variables.rb to reset all class variables of a given class

    module AutoCleanClassVariables
      def reset_class_variables
        self::CLASS_VARIABLES_TO_CLEAN.each do |var|
          class_variable_set var, nil
        end
      end
    end
    

    and calling this method from within config.after(:each), located in spec_helper.rb

    config.append_after(:each) do
      DatabaseCleaner.clean
    
      # Find all ActiveRecord classes having :reset_class_variables defined
      classes = ActiveSupport::DescendantsTracker.descendants(ActiveRecord::Base)
      classes.each do |cl|
        if cl.methods.include?(:reset_class_variables)
          cl.reset_class_variables
        end
      end
    end
    

    The models that need "cleaning" can bootstrap this behaviour:

    extend AutoCleanClassVariables
    CLASS_VARIABLES_TO_CLEAN = [:@@default]
    

    This way everything works fine, and there is no (unnecessary) reload of the class leading to problems if you try to compare objects of these classes with each other (see my earlier comment)