class RSpec::Core::Metadata::HashPopulator
managed by RSpec.
Used internally to populate metadata hashes with computed keys
@private
def build_description_from(parent_description=nil, my_description=nil)
def build_description_from(parent_description=nil, my_description=nil) return parent_description.to_s unless my_description separator = description_separator(parent_description, my_description) (parent_description.to_s + separator) << my_description.to_s end
def build_scoped_id_for(file_path)
def build_scoped_id_for(file_path) index = @index_provider.call(file_path).to_s parent_scoped_id = metadata.fetch(:scoped_id) { return index } "#{parent_scoped_id}:#{index}" end
def description_separator(parent_part, child_part)
def description_separator(parent_part, child_part) if parent_part.is_a?(Module) && child_part =~ /^(#|::|\.)/ ''.freeze else ' '.freeze end end
def ensure_valid_user_keys
def ensure_valid_user_keys RESERVED_KEYS.each do |key| next unless user_metadata.key?(key) raise <<-EOM.gsub(/^\s+\|/, '') |#{"*" * 50} |:#{key} is not allowed | |RSpec reserves some hash keys for its own internal use, |including :#{key}, which is used on: | | #{CallerFilter.first_non_rspec_line}. | |Here are all of RSpec's reserved hash keys: | | #{RESERVED_KEYS.join("\n ")} |#{"*" * 50} EOM end end
def file_path_and_line_number_from(backtrace)
def file_path_and_line_number_from(backtrace) first_caller_from_outside_rspec = backtrace.find { |l| l !~ CallerFilter::LIB_REGEX } first_caller_from_outside_rspec ||= backtrace.first /(.+?):(\d+)(?:|:\d+)/.match(first_caller_from_outside_rspec).captures end
def initialize(metadata, user_metadata, index_provider, description_args, block)
def initialize(metadata, user_metadata, index_provider, description_args, block) @metadata = metadata @user_metadata = user_metadata @index_provider = index_provider @description_args = description_args @block = block end
def populate
def populate ensure_valid_user_keys metadata[:execution_result] = Example::ExecutionResult.new metadata[:block] = block metadata[:description_args] = description_args metadata[:description] = build_description_from(*metadata[:description_args]) metadata[:full_description] = full_description metadata[:described_class] = described_class populate_location_attributes metadata.update(user_metadata) RSpec.configuration.apply_derived_metadata_to(metadata) end
def populate_location_attributes
def populate_location_attributes backtrace = user_metadata.delete(:caller) file_path, line_number = if backtrace file_path_and_line_number_from(backtrace) elsif block.respond_to?(:source_location) block.source_location else file_path_and_line_number_from(caller) end relative_file_path = Metadata.relative_path(file_path) absolute_file_path = File.expand_path(relative_file_path) metadata[:file_path] = relative_file_path metadata[:line_number] = line_number.to_i metadata[:location] = "#{relative_file_path}:#{line_number}" metadata[:absolute_file_path] = absolute_file_path metadata[:rerun_file_path] ||= relative_file_path metadata[:scoped_id] = build_scoped_id_for(absolute_file_path) end