class RSpec::Core::Formatters::Loader
interface.
not expected to be used directly, but only through the configuration
managing formatters used by a particular configuration. It is
`RSpec::Core::Formatters::Loader` is an internal class for
@api private
def self.formatters
- Api: - private
def self.formatters @formatters ||= {} end
def add(formatter_to_use, *paths)
- Private: -
def add(formatter_to_use, *paths) formatter_class = find_formatter(formatter_to_use) args = paths.map { |p| p.respond_to?(:puts) ? p : file_at(p) } if !Loader.formatters[formatter_class].nil? formatter = formatter_class.new(*args) @reporter.register_listener formatter, *notifications_for(formatter_class) elsif defined?(RSpec::LegacyFormatters) formatter = RSpec::LegacyFormatters.load_formatter formatter_class, *args @reporter.register_listener formatter, *formatter.notifications else line = ::RSpec::CallerFilter.first_non_rspec_line if line call_site = "Formatter added at: #{line}" else call_site = "The formatter was added via command line flag or your "+ "`.rspec` file." end RSpec.warn_deprecation <<-WARNING.gsub(/\s*\|/,' ') |The #{formatter_class} formatter uses the deprecated formatter |interface not supported directly by RSpec 3. | |To continue to use this formatter you must install the |`rspec-legacy_formatters` gem, which provides support |for legacy formatters or upgrade the formatter to a |compatible version. | |#{call_site} WARNING return end @formatters << formatter unless duplicate_formatter_exists?(formatter) formatter end
def built_in_formatter(key)
def built_in_formatter(key) case key.to_s when 'd', 'doc', 'documentation' DocumentationFormatter when 'h', 'html' HtmlFormatter when 'p', 'progress' ProgressFormatter when 'j', 'json' JsonFormatter end end
def custom_formatter(formatter_ref)
def custom_formatter(formatter_ref) if Class === formatter_ref formatter_ref elsif string_const?(formatter_ref) begin formatter_ref.gsub(/^::/,'').split('::').inject(Object) { |const,string| const.const_get string } rescue NameError require( path_for(formatter_ref) ) ? retry : raise end end end
def duplicate_formatter_exists?(new_formatter)
def duplicate_formatter_exists?(new_formatter) @formatters.any? do |formatter| formatter.class === new_formatter && formatter.output == new_formatter.output end end
def existing_formatter_implements?(notification)
def existing_formatter_implements?(notification) @reporter.registered_listeners(notification).any? end
def file_at(path)
def file_at(path) FileUtils.mkdir_p(File.dirname(path)) File.new(path, 'w') end
def find_formatter(formatter_to_use)
def find_formatter(formatter_to_use) built_in_formatter(formatter_to_use) || custom_formatter(formatter_to_use) || (raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?.") end
def initialize(reporter)
- Api: - private
def initialize(reporter) @formatters = [] @reporter = reporter self.default_formatter = 'progress' end
def notifications_for(formatter_class)
def notifications_for(formatter_class) formatter_class.ancestors.inject(Set.new) do |notifications, klass| notifications + Loader.formatters.fetch(klass) { Set.new } end end
def path_for(const_ref)
def path_for(const_ref) underscore_with_fix_for_non_standard_rspec_naming(const_ref) end
def setup_default(output_stream, deprecation_stream)
- Private: -
def setup_default(output_stream, deprecation_stream) if @formatters.empty? add default_formatter, output_stream end unless @formatters.any? { |formatter| DeprecationFormatter === formatter } add DeprecationFormatter, deprecation_stream, output_stream end if RSpec.configuration.profile_examples? && !existing_formatter_implements?(:dump_profile) add RSpec::Core::Formatters::ProfileFormatter, output_stream end end
def string_const?(str)
def string_const?(str) str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str end
def underscore(camel_cased_word)
def underscore(camel_cased_word) word = camel_cased_word.to_s.dup word.gsub!(/::/, '/') word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') word.tr!("-", "_") word.downcase! word end
def underscore_with_fix_for_non_standard_rspec_naming(string)
def underscore_with_fix_for_non_standard_rspec_naming(string) underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2') end