joker1007/ghost_writer

View on GitHub
lib/ghost_writer.rb

Summary

Maintainability
A
0 mins
Test Coverage
require "ghost_writer/version"
require "ghost_writer/document"
require "ghost_writer/document_index"
require "active_support/concern"
require "oj"
require "json"

module GhostWriter
  extend ActiveSupport::Concern

  module Format
    autoload "Markdown", "ghost_writer/format/markdown"
    autoload "Rst", "ghost_writer/format/rst"
    autoload "Rack", "ghost_writer/format/rack"
  end

  DEFAULT_OUTPUT_DIR = "api_examples".freeze
  DEFAULT_FORMAT = :markdown
  DOCUMENT_INDEX_FILENAME = "document_index".freeze

  class << self
    attr_writer :output_dir, :output_flag, :output_format
    attr_accessor :github_base_url

    def document_group
      @document_group ||= {}
      @document_group
    end

    def generate_api_doc
      if output_flag
        unless File.exist?(output_dir)
          FileUtils.mkdir_p(output_dir)
        end
        document_index = GhostWriter::DocumentIndex.new(output_dir + "#{DOCUMENT_INDEX_FILENAME}", document_group, GhostWriter.output_format)
        document_index.write_file(format: output_format)
        document_group.each do |output, docs|
          docs.sort_by!(&:location)
          initial = docs.shift
          initial.header = true
          initial.write_file(format: output_format, overwrite: true)
          docs.each {|d| d.write_file(format: output_format) }
        end

        document_group.clear
      end
    end

    def output_flag
      !!(@output_flag ? @output_flag : ENV["GENERATE_API_DOC"])
    end

    def output_dir
      @output_dir ? Pathname(@output_dir) : Pathname(DEFAULT_OUTPUT_DIR)
    end

    def output_format
      @output_format || DEFAULT_FORMAT
    end
  end

  def collect_example(example)
    output = doc_dir + doc_name(example)
    document = GhostWriter::Document.new(output, {
      title: "#{described_class} #{doc_name(example).titleize}",
      description: example.full_description.dup,
      location: example.location.dup,
      request_method: request.env["REQUEST_METHOD"],
      path_info: request.env["PATH_INFO"],
      param_example: controller.params.reject {|key, val| key == "controller" || key == "action"},
      status_code: response.status,
      response_body: response.body,
      format: GhostWriter.output_format
    })

    GhostWriter.document_group[output] ||= []
    GhostWriter.document_group[output] << document
  end

  private
  def doc_dir
    GhostWriter.output_dir + described_class.to_s.underscore
  end

  def doc_name(example)
    metadata = example.metadata[:generate_api_doc] || example.metadata[:ghost_writer]
    case metadata
    when String, Symbol
      example.metadata[:generate_api_doc].to_s
    else
      controller.action_name
    end
  end

  included do
    after do |example_or_group|
      example = example_or_group.is_a?(RSpec::Core::Example) ?
        example_or_group :
        example_or_group.example
      target_type = example.metadata[:type] == :controller || example.metadata[:type] == :request
      target_metadata = example.metadata[:generate_api_doc] || example.metadata[:ghost_writer]
      if target_type && target_metadata
        collect_example(example) if GhostWriter.output_flag
      end
    end
  end
end