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

One Comment on “class reloading in ruby”

  1. mk Says:

    beware of losing changes to reopened classes with this approach!

    I’m not sure that there’s any way around it, but something to keep in mind.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.