diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ababb76a5..4d802d81c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2020-03-01 03:15:48 +0900 using RuboCop version 0.68.1. +# on 2020-04-03 00:51:53 +0900 using RuboCop version 0.68.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -163,12 +163,11 @@ Lint/InheritException: Exclude: - 'lib/annotate/annotate_models.rb' -# Offense count: 2 +# Offense count: 1 # Configuration parameters: MaximumRangeSize. Lint/MissingCopEnableDirective: Exclude: - 'lib/annotate/annotate_models.rb' - - 'lib/annotate/annotate_routes.rb' # Offense count: 2 Lint/RescueException: @@ -213,7 +212,7 @@ Naming/AccessorMethodName: Exclude: - 'lib/annotate.rb' -# Offense count: 103 +# Offense count: 102 # Configuration parameters: Blacklist. # Blacklist: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) Naming/HeredocDelimiterNaming: @@ -235,12 +234,13 @@ Naming/UncommunicativeMethodParamName: Exclude: - 'Rakefile' -# Offense count: 1 +# Offense count: 2 # Configuration parameters: EnforcedStyle. # SupportedStyles: inline, group Style/AccessModifierDeclarations: Exclude: - 'lib/annotate/annotate_models.rb' + - 'lib/annotate/annotate_routes/header_generator.rb' # Offense count: 1 Style/CaseEquality: @@ -266,7 +266,7 @@ Style/Dir: Exclude: - 'bin/annotate' -# Offense count: 9 +# Offense count: 10 Style/Documentation: Exclude: - 'spec/**/*' @@ -275,6 +275,7 @@ Style/Documentation: - 'lib/annotate/active_record_patch.rb' - 'lib/annotate/annotate_models.rb' - 'lib/annotate/annotate_routes.rb' + - 'lib/annotate/annotate_routes/header_generator.rb' - 'lib/annotate/annotate_routes/helpers.rb' - 'lib/annotate/version.rb' - 'lib/generators/annotate/install_generator.rb' @@ -293,14 +294,13 @@ Style/ExpandPathArguments: Exclude: - 'annotate.gemspec' -# Offense count: 10 +# Offense count: 9 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: format, sprintf, percent Style/FormatString: Exclude: - 'lib/annotate/annotate_models.rb' - - 'lib/annotate/annotate_routes.rb' # Offense count: 23 # Configuration parameters: EnforcedStyle. @@ -309,7 +309,7 @@ Style/FormatStringToken: Exclude: - 'lib/annotate/annotate_models.rb' -# Offense count: 27 +# Offense count: 28 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: when_needed, always, never @@ -338,7 +338,7 @@ Style/IfUnlessModifier: - 'Rakefile' - 'bin/annotate' - 'lib/annotate/annotate_models.rb' - - 'lib/annotate/annotate_routes.rb' + - 'lib/annotate/annotate_routes/header_generator.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -432,7 +432,7 @@ Style/RedundantSelf: Exclude: - 'lib/tasks/annotate_models_migrate.rake' -# Offense count: 13 +# Offense count: 12 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, AllowInnerSlashes. # SupportedStyles: slashes, percent_r, mixed @@ -440,7 +440,6 @@ Style/RegexpLiteral: Exclude: - 'Rakefile' - 'lib/annotate/annotate_models.rb' - - 'lib/annotate/annotate_routes.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -521,7 +520,7 @@ Style/UnneededPercentQ: Exclude: - 'annotate.gemspec' -# Offense count: 377 +# Offense count: 375 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https diff --git a/lib/annotate/annotate_routes.rb b/lib/annotate/annotate_routes.rb index d1fed3353..75cc421ed 100644 --- a/lib/annotate/annotate_routes.rb +++ b/lib/annotate/annotate_routes.rb @@ -1,5 +1,3 @@ -# rubocop:disable Metrics/ModuleLength - # == Annotate Routes # # Based on: @@ -21,18 +19,15 @@ # require_relative './annotate_routes/helpers' +require_relative './annotate_routes/header_generator' module AnnotateRoutes - PREFIX = '== Route Map'.freeze - PREFIX_MD = '## Route Map'.freeze - HEADER_ROW = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'].freeze - 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(header(options), content, header_position, options) + new_content = annotate_routes(HeaderGenerator.generate(options), content, header_position, options) new_text = new_content.join("\n") if rewrite_contents(existing_text, new_text) @@ -71,49 +66,6 @@ def routes_file @routes_rb ||= File.join('config', 'routes.rb') end - def header(options = {}) - routes_map = app_routes_map(options) - - magic_comments_map, routes_map = Helpers.extract_magic_comments_from_array(routes_map) - - out = [] - - magic_comments_map.each do |magic_comment| - out << magic_comment - end - out << '' if magic_comments_map.any? - - out << comment(options[:wrapper_open]) if options[:wrapper_open] - - out << comment(options[:format_markdown] ? PREFIX_MD : PREFIX) + (options[:timestamp] ? " (Updated #{Time.now.strftime('%Y-%m-%d %H:%M')})" : '') - out << comment - return out if routes_map.size.zero? - - maxs = [HEADER_ROW.map(&:size)] + routes_map[1..-1].map { |line| line.split.map(&:size) } - - if options[:format_markdown] - max = maxs.map(&:max).compact.max - - out << comment(content(HEADER_ROW, maxs, options)) - out << comment(content(['-' * max, '-' * max, '-' * max, '-' * max], maxs, options)) - else - out << comment(content(routes_map[0], maxs, options)) - end - - out += routes_map[1..-1].map { |line| comment(content(options[:format_markdown] ? line.split(' ') : line, maxs, options)) } - out << comment(options[:wrapper_close]) if options[:wrapper_close] - - out - end - - def comment(row = '') - if row == '' - '#' - else - "# #{row}" - end - end - def strip_on_removal(content, header_position) if header_position == :before content.shift while content.first == '' @@ -162,32 +114,5 @@ def annotate_routes(header, content, header_position, options = {}) new_content end - - def app_routes_map(options) - routes_map = `rake routes`.chomp("\n").split(/\n/, -1) - - # In old versions of Rake, the first line of output was the cwd. Not so - # much in newer ones. We ditch that line if it exists, and if not, we - # keep the line around. - routes_map.shift if routes_map.first =~ /^\(in \// - - # Skip routes which match given regex - # Note: it matches the complete line (route_name, path, controller/action) - if options[:ignore_routes] - routes_map.reject! { |line| line =~ /#{options[:ignore_routes]}/ } - end - - routes_map - end - - def content(line, maxs, options = {}) - return line.rstrip unless options[:format_markdown] - - line.each_with_index.map do |elem, index| - min_length = maxs.map { |arr| arr[index] }.max || 0 - - sprintf("%-#{min_length}.#{min_length}s", elem.tr('|', '-')) - end.join(' | ') - end end end diff --git a/lib/annotate/annotate_routes/header_generator.rb b/lib/annotate/annotate_routes/header_generator.rb new file mode 100644 index 000000000..941f9bb99 --- /dev/null +++ b/lib/annotate/annotate_routes/header_generator.rb @@ -0,0 +1,97 @@ +require_relative './helpers' + +module AnnotateRoutes + class HeaderGenerator + PREFIX = '== Route Map'.freeze + PREFIX_MD = '## Route Map'.freeze + HEADER_ROW = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'].freeze + + class << self + def generate(options = {}) + routes_map = app_routes_map(options) + new(options, routes_map).generate + end + + private :new + + private + + def app_routes_map(options) + routes_map = `rake routes`.chomp("\n").split(/\n/, -1) + + # In old versions of Rake, the first line of output was the cwd. Not so + # much in newer ones. We ditch that line if it exists, and if not, we + # keep the line around. + routes_map.shift if routes_map.first =~ %r{^\(in \/} + + # Skip routes which match given regex + # Note: it matches the complete line (route_name, path, controller/action) + if options[:ignore_routes] + routes_map.reject! { |line| line =~ /#{options[:ignore_routes]}/ } + end + + routes_map + end + end + + def initialize(options, routes_map) + @options = options + @routes_map = routes_map + end + + def generate + magic_comments_map, contents_without_magic_comments = Helpers.extract_magic_comments_from_array(routes_map) + + out = [] + + magic_comments_map.each do |magic_comment| + out << magic_comment + end + out << '' if magic_comments_map.any? + + out << comment(options[:wrapper_open]) if options[:wrapper_open] + + out << comment(options[:format_markdown] ? PREFIX_MD : PREFIX) + (options[:timestamp] ? " (Updated #{Time.now.strftime('%Y-%m-%d %H:%M')})" : '') + out << comment + return out if contents_without_magic_comments.size.zero? + + maxs = [HEADER_ROW.map(&:size)] + contents_without_magic_comments[1..-1].map { |line| line.split.map(&:size) } + + if options[:format_markdown] + max = maxs.map(&:max).compact.max + + out << comment(content(HEADER_ROW, maxs)) + out << comment(content(['-' * max, '-' * max, '-' * max, '-' * max], maxs)) + else + out << comment(content(contents_without_magic_comments[0], maxs)) + end + + out += contents_without_magic_comments[1..-1].map { |line| comment(content(options[:format_markdown] ? line.split(' ') : line, maxs)) } + out << comment(options[:wrapper_close]) if options[:wrapper_close] + + out + end + + private + + attr_reader :options, :routes_map + + def comment(row = '') + if row == '' + '#' + else + "# #{row}" + end + end + + def content(line, maxs) + return line.rstrip unless options[:format_markdown] + + line.each_with_index.map do |elem, index| + min_length = maxs.map { |arr| arr[index] }.max || 0 + + format("%-#{min_length}.#{min_length}s", elem.tr('|', '-')) + end.join(' | ') + end + end +end diff --git a/spec/lib/annotate/annotate_routes_spec.rb b/spec/lib/annotate/annotate_routes_spec.rb index dc4400a35..a0ed118cc 100644 --- a/spec/lib/annotate/annotate_routes_spec.rb +++ b/spec/lib/annotate/annotate_routes_spec.rb @@ -49,7 +49,7 @@ expect(File).to receive(:exist?).with(ROUTE_FILE).and_return(true).once expect(File).to receive(:read).with(ROUTE_FILE).and_return(route_file_content).once - expect(AnnotateRoutes).to receive(:`).with('rake routes').and_return(rake_routes_result).once + expect(AnnotateRoutes::HeaderGenerator).to receive(:`).with('rake routes').and_return(rake_routes_result).once end context 'When the result of `rake routes` is present' do