0

In the following situation, where include_class is a preference, can I somehow dynamically change the value of include_class and reload Image such that it instead includes the new value of include_class?

module Foo
  included do
    @test_var = :foo
  end
end

module Bar
  included do
    @test_var = :bar
  end
end

Config.include_class = Foo

class Image
  include Config.include_class
end

# ... run tests with default configuration for Image, where Image.test_var = :foo

Config.include_class = OtherClass

# ... how can I reload or re-evaluate Image such that Image.test_var = :bar?

Context

I am trying to test whether a configuration option (that is normally set by an initializer) has the correct effects on the application. Because this is part of a test suite the the modules and classes might be loaded before and all configuration changes need to be reset after the test.

Nick Belzer
  • 91
  • 1
  • 6

1 Answers1

1

I'd suggest to use refinements instead, in this case class will be reset after the test (on any other stuff). I implemented an example without active_concern, but the idea should be clear. This example can be executed with plain ruby as a single script.

# This part is just to keep close to your example
class Config
  def self.include_class=(klass)
    @@include_class = klass
  end

  def self.include_class
    @@include_class ||= nil
  end
end

# Assuming Bar is a default module and Foo will be used in tests
module Bar
  def print_something
    puts 'I am Bar'
  end
end

module Foo
  def print_something
    puts 'I am Foo'
  end
end

# Setting default module
Config.include_class = Bar

# Defining Image class
class Image
  include Config.include_class
end

#Changing config
Config.include_class = Foo

# This is a refinement
module ImagePatch
  # It will include current Config.include_class
  # Note that methods from Bar that are not present in Foo will not be removed
  refine Image do
    include Config.include_class
  end
end

# Here we will create module where refinement is activated
module TestEnv
  # Activating the patch
  using ImagePatch
  Image.new.print_something #=>I am Foo
end

#Outside of the TestEnv module we enjoy the default Image class
Image.new.print_something #=>I am Bar
Pavel Oganesyan
  • 6,774
  • 4
  • 46
  • 84
  • Thank you, this solves the question perfectly. I was able to use the idea of refinements and a custom class as [described in this answer](https://stackoverflow.com/a/32277975/7868972) to solve my specific use case. – Nick Belzer Jan 18 '22 at 14:32