Sometimes I want to verify the value within a constant is handled in a certain way, independently of what the actual value in the constant is defined as.
So I change it, temporarily.
ApplicationConfig.override_constant(:RECORD_ANALYTICS, false) do puts "For the duration of this block, RECORD_ANALYTICS is #{ApplicationConfig::RECORD_ANALYTICS}" end
# Override the value of a Module Constant for the duration of a block. class Module def override_constant constant_name, new_value raise ArgumentError, 'No block provided to establish a context in which the constant is overridden' unless block_given? # Cannot override unless constant is defined in Module raise NameError, "#{self} does not define #{constant_name}" unless const_defined?(constant_name) # Store original value to replace it at the end original_value = const_get(constant_name) # Remove original definition remove_const constant_name # Insert alternative definition const_set constant_name, new_value begin yield ensure # Remove alternative definition remove_const constant_name # Restore original definition const_set constant_name, original_value end end end
class OverrideConstantTest < Test::Unit::TestCase module TestModule DEFINED_CONSTANT = true end def test_should_raise_argument_error_when_block_is_not_provided assert_raise_with_error_message ArgumentError, :error_message => 'No block provided to establish a context in which the constant is overridden' do TestModule.override_constant :DEFINED_CONSTANT, true end end def test_should_raise_error_when_module_does_not_define_constant assert_raise_with_error_message NameError, :error_message => 'OverrideConstantTest::TestModule does not define NO_SUCH_CONSTANT' do TestModule.override_constant :NO_SUCH_CONSTANT, true do end end end def test_should_alter_value_of_constant_for_duration_of_block assert_equal true, TestModule::DEFINED_CONSTANT TestModule.override_constant :DEFINED_CONSTANT, false do assert_equal false, TestModule::DEFINED_CONSTANT end assert_equal true, TestModule::DEFINED_CONSTANT end end
Updated to ensure constants are returned to their original state, even if the yielded block raises an error.
September 11th, 2007