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.
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