ctran/annotate_models

View on GitHub
lib/annotate/annotate_routes.rb

Summary

Maintainability
A
2 hrs
Test Coverage
# == Annotate Routes
#
# Based on:
#
#
#
# Prepends the output of "rake routes" to the top of your routes.rb file.
# Yes, it's simple but I'm thick and often need a reminder of what my routes
# mean.
#
# Running this task will replace any existing route comment generated by the
# task. Best to back up your routes file before running:
#
# Author:
#  Gavin Montague
#  gavin@leftbrained.co.uk
#
# Released under the same license as Ruby. No Support. No Warranty.
#

require_relative './annotate_routes/helpers'
require_relative './annotate_routes/header_generator'

module AnnotateRoutes
  class << self
    def do_annotations(options = {})
      if routes_file_exist?
        existing_text = File.read(routes_file)
        content, header_position = Helpers.strip_annotations(existing_text)
        new_content = annotate_routes(HeaderGenerator.generate(options), content, header_position, options)
        new_text = new_content.join("\n")
        if rewrite_contents(existing_text, new_text, options[:frozen])
          puts "#{routes_file} was annotated."
        else
          puts "#{routes_file} was not changed."
        end
      else
        puts "#{routes_file} could not be found."
      end
    end

    def remove_annotations(options={})
      if routes_file_exist?
        existing_text = File.read(routes_file)
        content, header_position = Helpers.strip_annotations(existing_text)
        new_content = strip_on_removal(content, header_position)
        new_text = new_content.join("\n")
        if rewrite_contents(existing_text, new_text, options[:frozen])
          puts "Annotations were removed from #{routes_file}."
        else
          puts "#{routes_file} was not changed (Annotation did not exist)."
        end
      else
        puts "#{routes_file} could not be found."
      end
    end

    private

    def routes_file_exist?
      File.exist?(routes_file)
    end

    def routes_file
      @routes_rb ||= File.join('config', 'routes.rb')
    end

    def strip_on_removal(content, header_position)
      if header_position == :before
        content.shift while content.first == ''
      elsif header_position == :after
        content.pop while content.last == ''
      end

      # Make sure we end on a trailing newline.
      content << '' unless content.last == ''

      # TODO: If the user buried it in the middle, we should probably see about
      # TODO: preserving a single line of space between the content above and
      # TODO: below...
      content
    end

    def rewrite_contents(existing_text, new_text, frozen)
      content_changed = (existing_text != new_text)

      if content_changed
        abort "annotate error. #{routes_file} needs to be updated, but annotate was run with `--frozen`." if frozen
        File.open(routes_file, 'wb') { |f| f.puts(new_text) }
      end

      content_changed
    end

    def annotate_routes(header, content, header_position, options = {})
      magic_comments_map, content = Helpers.extract_magic_comments_from_array(content)
      if %w(before top).include?(options[:position_in_routes])
        header = header << '' if content.first != ''
        magic_comments_map << '' if magic_comments_map.any?
        new_content = magic_comments_map + header + content
      else
        # Ensure we have adequate trailing newlines at the end of the file to
        # ensure a blank line separating the content from the annotation.
        content << '' unless content.last == ''

        # We're moving something from the top of the file to the bottom, so ditch
        # the spacer we put in the first time around.
        content.shift if header_position == :before && content.first == ''

        new_content = magic_comments_map + content + header
      end

      # Make sure we end on a trailing newline.
      new_content << '' unless new_content.last == ''

      new_content
    end
  end
end