Run the provided block and detect the new constants that were loaded during its execution. Constants may only be regarded as ‘new’ once — so if the block calls new_constants_in again, then the constants defined within the inner call will not be reported in this one.
If the provided block does not run to completion, and instead raises an exception, any new constants are regarded as being only partially defined and will be removed immediately.
Source Code
# File active_support/dependencies.rb, line 313 def new_constants_in(*descs) log_call(*descs) # Build the watch frames. Each frame is a tuple of # [module_name_as_string, constants_defined_elsewhere] watch_frames = descs.collect do |desc| if desc.is_a? Module mod_name = desc.name initial_constants = desc.local_constants elsif desc.is_a?(String) || desc.is_a?(Symbol) mod_name = desc.to_s # Handle the case where the module has yet to be defined. initial_constants = if qualified_const_defined?(mod_name) mod_name.constantize.local_constants else [] end else raise Argument, "#{desc.inspect} does not describe a module!" end [mod_name, initial_constants] end constant_watch_stack.concat watch_frames aborting = true begin yield # Now yield to the code that is to define new constants. aborting = false ensure # Find the new constants. new_constants = watch_frames.collect do |mod_name, prior_constants| # Module still doesn't exist? Treat it as if it has no constants. next [] unless qualified_const_defined?(mod_name) mod = mod_name.constantize next [] unless mod.is_a? Module new_constants = mod.local_constants - prior_constants # Make sure no other frames takes credit for these constants. constant_watch_stack.each do |frame_name, constants| constants.concat new_constants if frame_name == mod_name end new_constants.collect do |suffix| mod_name == "Object" ? suffix : "#{mod_name}::#{suffix}" end end.flatten log "New constants: #{new_constants * ', '}" if aborting log "Error during loading, removing partially loaded constants " new_constants.each { |name| remove_constant name } new_constants.clear end end return new_constants ensure # Remove the stack frames that we added. if defined?(watch_frames) && ! watch_frames.empty? frame_ids = watch_frames.collect(&:object_id) constant_watch_stack.delete_if do |watch_frame| frame_ids.include? watch_frame.object_id end end end
<code/>and<pre/>for code samples.