class reloading in ruby

Ever wanted to undefine a class in ruby and reload it afterwards? Needed this as I wanted to restart a test suite with the models using table names – tests for the has_many_polymorphs plugin. It’s a dirty hack and doesn’t work with instantiated fixtures, but at least it makes shure the same tests run on models with table_name set.

To “reload a class” you unset the class constant in the main object name space and then reload the class source file. In my case I wanted the table name to be set before the association creation macros (has_many, belongs_to etc.) are called, so they use the correct table name.

This works by unsetting the class constant, then recreating the class manually by setting the class name constant to the newly created class, setting the table name and afterwards loading the model file, enhancing the class we created before with the table name already set.

class PolymorphTableTest < PolymorphTest

  fixtures :test_petfoods, :test_cats, :test_dogs, :test_wild_boars
  CLASSES = [:Cat, :D og, :EatersParent, :WildBoar, :Kitten, :Tabby, :P etfood]

  def setup
    names = CLASSES
    # unset classes
    Object.class_eval do
      names.each do |clazz|
        remove_const clazz.to_s if const_defined? clazz.to_s
      end
    end

    # create new and set table names
    [:Dog, :Cat, :WildBoar, :EatersParent, :P etfood].each do |name|
      Object.class_eval do
        clazz = const_set(name.to_s, Class.new(ActiveRecord::Base))
        clazz.set_table_name "test_#{name.to_s.pluralize.underscore}"
      end
    end

    # reload model files
    names.each do |clazz|
      load "#{clazz.to_s.underscore}.rb"
    end
    super
  end

  def teardown
    super
    names = CLASSES

    # unset model classes
    Object.class_eval do
      names.each do |clazz|
        remove_const clazz.to_s if const_defined? clazz.to_s
      end
    end

    # reload model files
    names.each do |clazz|
      load "#{clazz.to_s.underscore}.rb"
    end

  end
end
Explore posts in the same categories: Ruby/Rails

Comment: