From 4e2946d19fb8f69afefba4ddc6ecc2bbc683c5df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Sun, 28 Apr 2019 10:56:44 -0700 Subject: [PATCH 01/27] Update ruby_dep requirement from 1.3.1 to 1.5.0 (#605) Updates the requirements on [ruby_dep](https://github.com/e2/ruby_dep) to permit the latest version. - [Release notes](https://github.com/e2/ruby_dep/releases) - [Commits](https://github.com/e2/ruby_dep/compare/v1.3.1...v1.5.0) Signed-off-by: dependabot[bot] --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 8e80a7a1f..ccfc11bc9 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ group :development, :test do gem 'coveralls' gem 'overcommit' - gem 'ruby_dep', '1.3.1' + gem 'ruby_dep', '1.5.0' platforms :mri, :mingw do gem 'pry', require: false From 289621b82c8f1a6a56c0882d4ea34aabd722fcdf Mon Sep 17 00:00:00 2001 From: Shu Fujita Date: Mon, 29 Apr 2019 02:57:39 +0900 Subject: [PATCH 02/27] Make methods private in AnnotateRoutes (#598) In AnnotateRoutes, there were many public methods that is not used in other classes or modules. Before my extension, I made these methods private and sort them in order of appearance. All tests were passed. Please trace each commits carefully. I didn't nothing special. The commits consist of coordinating code. --- lib/annotate/annotate_routes.rb | 296 ++++++++++++++++---------------- 1 file changed, 149 insertions(+), 147 deletions(-) diff --git a/lib/annotate/annotate_routes.rb b/lib/annotate/annotate_routes.rb index 276c2cbc1..4ad9f9136 100644 --- a/lib/annotate/annotate_routes.rb +++ b/lib/annotate/annotate_routes.rb @@ -25,14 +25,53 @@ module AnnotateRoutes HEADER_ROW = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'] class << self - def content(line, maxs, options = {}) - return line.rstrip unless options[:format_markdown] + def do_annotations(options = {}) + return unless routes_exists? + existing_text = File.read(routes_file) - line.each_with_index.map do |elem, index| - min_length = maxs.map { |arr| arr[index] }.max || 0 + if rewrite_contents_with_header(existing_text, header(options), options) + puts "#{routes_file} annotated." + end + end - sprintf("%-#{min_length}.#{min_length}s", elem.tr('|', '-')) - end.join(' | ') + def remove_annotations(_options={}) + return unless routes_exists? + existing_text = File.read(routes_file) + content, where_header_found = strip_annotations(existing_text) + new_content = strip_on_removal(content, where_header_found) + if rewrite_contents(existing_text, new_content) + puts "Removed annotations from #{routes_file}." + end + end + + private + + def routes_exists? + routes_exists = File.exists?(routes_file) + puts "Can't find routes.rb" unless routes_exists + + routes_exists + end + + def routes_file + @routes_rb ||= File.join('config', 'routes.rb') + end + + def rewrite_contents_with_header(existing_text, header, options = {}) + content, where_header_found = strip_annotations(existing_text) + new_content = annotate_routes(header, content, where_header_found, options) + + # Make sure we end on a trailing newline. + new_content << '' unless new_content.last == '' + new_text = new_content.join("\n") + + if existing_text == new_text + puts "#{routes_file} unchanged." + false + else + File.open(routes_file, 'wb') { |f| f.puts(new_text) } + true + end end def header(options = {}) @@ -70,180 +109,143 @@ def header(options = {}) out end - def do_annotations(options = {}) - return unless routes_exists? - existing_text = File.read(routes_file) - - if rewrite_contents_with_header(existing_text, header(options), options) - puts "#{routes_file} annotated." + # TODO: write the method doc using ruby rdoc formats + # where_header_found => This will either be :before, :after, or + # a number. If the number is > 0, the + # annotation was found somewhere in the + # middle of the file. If the number is + # zero, no annotation was found. + def strip_annotations(content) + real_content = [] + mode = :content + header_found_at = 0 + + content.split(/\n/, -1).each_with_index do |line, line_number| + if mode == :header && line !~ /\s*#/ + mode = :content + real_content << line unless line.blank? + elsif mode == :content + if line =~ /^\s*#\s*== Route.*$/ + header_found_at = line_number + 1 # index start's at 0 + mode = :header + else + real_content << line + end + end end + + where_header_found(real_content, header_found_at) end - def remove_annotations(_options={}) - return unless routes_exists? - existing_text = File.read(routes_file) - content, where_header_found = strip_annotations(existing_text) - new_content = strip_on_removal(content, where_header_found) - if rewrite_contents(existing_text, new_content) - puts "Removed annotations from #{routes_file}." + def strip_on_removal(content, where_header_found) + if where_header_found == :before + content.shift while content.first == '' + elsif where_header_found == :after + content.pop while content.last == '' end - end - end - def self.magic_comment_matcher - Regexp.new(/(^#\s*encoding:.*)|(^# coding:.*)|(^# -\*- coding:.*)|(^# -\*- encoding\s?:.*)|(^#\s*frozen_string_literal:.+)|(^# -\*- frozen_string_literal\s*:.+-\*-)/) - end + # 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 - # @param [Array] content - # @return [Array] all found magic comments - # @return [Array] content without magic comments - def self.extract_magic_comments_from_array(content_array) - magic_comments = [] - new_content = [] + # @param [String, Array] + def rewrite_contents(existing_text, new_content) + # Make sure we end on a trailing newline. + new_content << '' unless new_content.last == '' + new_text = new_content.join("\n") - content_array.map do |row| - if row =~ magic_comment_matcher - magic_comments << row.strip + if existing_text == new_text + puts "#{routes_file} unchanged." + false else - new_content << row + File.open(routes_file, 'wb') { |f| f.puts(new_text) } + true end end - [magic_comments, new_content] - end - - def self.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 self.routes_file - @routes_rb ||= File.join('config', 'routes.rb') - end + def annotate_routes(header, content, where_header_found, options = {}) + magic_comments_map, content = 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 == '' - def self.routes_exists? - routes_exists = File.exists?(routes_file) - puts "Can't find routes.rb" unless routes_exists + # 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 where_header_found == :before && content.first == '' - routes_exists - end + new_content = magic_comments_map + content + header + end - # @param [String, Array] - def self.rewrite_contents(existing_text, new_content) - # Make sure we end on a trailing newline. - new_content << '' unless new_content.last == '' - new_text = new_content.join("\n") - - if existing_text == new_text - puts "#{routes_file} unchanged." - false - else - File.open(routes_file, 'wb') { |f| f.puts(new_text) } - true + new_content end - end - def self.rewrite_contents_with_header(existing_text, header, options = {}) - content, where_header_found = strip_annotations(existing_text) - new_content = annotate_routes(header, content, where_header_found, options) + def app_routes_map(options) + routes_map = `rake routes`.chomp("\n").split(/\n/, -1) - # Make sure we end on a trailing newline. - new_content << '' unless new_content.last == '' - new_text = new_content.join("\n") + # 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 \// - if existing_text == new_text - puts "#{routes_file} unchanged." - false - else - File.open(routes_file, 'wb') { |f| f.puts(new_text) } - true - end - end + # 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 - def self.annotate_routes(header, content, where_header_found, options = {}) - magic_comments_map, content = 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 where_header_found == :before && content.first == '' - - new_content = magic_comments_map + content + header + routes_map end - new_content - end + # @param [Array] content + # @return [Array] all found magic comments + # @return [Array] content without magic comments + def extract_magic_comments_from_array(content_array) + magic_comments = [] + new_content = [] - # TODO: write the method doc using ruby rdoc formats - # where_header_found => This will either be :before, :after, or - # a number. If the number is > 0, the - # annotation was found somewhere in the - # middle of the file. If the number is - # zero, no annotation was found. - def self.strip_annotations(content) - real_content = [] - mode = :content - header_found_at = 0 - - content.split(/\n/, -1).each_with_index do |line, line_number| - if mode == :header && line !~ /\s*#/ - mode = :content - real_content << line unless line.blank? - elsif mode == :content - if line =~ /^\s*#\s*== Route.*$/ - header_found_at = line_number + 1 # index start's at 0 - mode = :header + content_array.map do |row| + if row =~ magic_comment_matcher + magic_comments << row.strip else - real_content << line + new_content << row end end + + [magic_comments, new_content] end - where_header_found(real_content, header_found_at) - 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 - def self.where_header_found(real_content, header_found_at) - # By default assume the annotation was found in the middle of the file + sprintf("%-#{min_length}.#{min_length}s", elem.tr('|', '-')) + end.join(' | ') + end - # ... unless we have evidence it was at the beginning ... - return real_content, :before if header_found_at == 1 + def where_header_found(real_content, header_found_at) + # By default assume the annotation was found in the middle of the file - # ... or that it was at the end. - return real_content, :after if header_found_at >= real_content.count + # ... unless we have evidence it was at the beginning ... + return real_content, :before if header_found_at == 1 - # and the default - return real_content, header_found_at - end + # ... or that it was at the end. + return real_content, :after if header_found_at >= real_content.count - def self.strip_on_removal(content, where_header_found) - if where_header_found == :before - content.shift while content.first == '' - elsif where_header_found == :after - content.pop while content.last == '' + # and the default + return real_content, header_found_at end - # 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 + def magic_comment_matcher + Regexp.new(/(^#\s*encoding:.*)|(^# coding:.*)|(^# -\*- coding:.*)|(^# -\*- encoding\s?:.*)|(^#\s*frozen_string_literal:.+)|(^# -\*- frozen_string_literal\s*:.+-\*-)/) + end end end From b56e89df793aacb5371e16e18eb42ddf39936902 Mon Sep 17 00:00:00 2001 From: Cuong Tran Date: Wed, 8 May 2019 10:41:12 -0700 Subject: [PATCH 03/27] Move gem publish to separate stage in Travis (#618) Travis was trying to publish gem multiple times in the matrix builds. This should restrict the gem publish to a single build. --- .travis.yml | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 623154090..75b0d9acb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,23 +2,36 @@ sudo: false language: ruby rvm: - 2.2.7 -- 2.3.4 -- 2.4.1 +- 2.3.8 +- 2.4.6 +- 2.5.5 - 2.6.0 +- 2.6.1 +- 2.6.2 +- 2.6.3 - ruby-head + matrix: allow_failures: - rvm: ruby-head + before_install: - gem update --system - gem update bundler + script: - bundle exec rubocop && bundle exec rspec -deploy: - provider: rubygems - api_key: - secure: Y7DUitak26kcRAAkgph/7m6Y1wHeObD0BelSSJbmCfjkRd/qaVy7fz9VvHL9zxlRJtLGVHInyCnwcfzinibY6OFd3MoMYHKv8GFa2LxLJNEVSY46KQYFxfH5JTg1ejh6ldoJRRBoeOx9dcWS80pRNjYMKPGnpSz7yDBl1azibFs= - gem: annotate - on: - tags: true - repo: ctran/annotate_models + +jobs: + include: + - stage: gem release + if: tag =~ ^v + rvm: 2.6.0 + script: echo "Deploying to rubygems.org ..." + deploy: + provider: rubygems + api_key: $RUBYGEMS_API_KEY + gem: annotate + on: + tags: true + repo: ctran/annotate_models From 55c23eb56cfe99baee70554d1dfadca07944b6d0 Mon Sep 17 00:00:00 2001 From: Colby Melvin Date: Thu, 23 May 2019 14:31:14 -0500 Subject: [PATCH 04/27] Fix annotations for columns with long data types (#622) Handle potential negative padding in `#mb_chars_ljust` when having a `col_length` > 16, the default hardcoded value of `bare_type_allowance`. --- lib/annotate/annotate_models.rb | 6 +++++- spec/annotate/annotate_models_spec.rb | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/annotate/annotate_models.rb b/lib/annotate/annotate_models.rb index 6a46d0f9f..1d64c383d 100644 --- a/lib/annotate/annotate_models.rb +++ b/lib/annotate/annotate_models.rb @@ -910,7 +910,11 @@ def width(string) def mb_chars_ljust(string, length) string = string.to_s padding = length - width(string) - string + (' ' * padding) + if padding > 0 + string + (' ' * padding) + else + string[0..length-1] + end end end diff --git a/spec/annotate/annotate_models_spec.rb b/spec/annotate/annotate_models_spec.rb index 21dff3966..f23cad117 100644 --- a/spec/annotate/annotate_models_spec.rb +++ b/spec/annotate/annotate_models_spec.rb @@ -943,7 +943,8 @@ def self.when_called_with(options = {}) [:active, :boolean, { limit: 1, comment: 'ACTIVE' }], [:name, :string, { limit: 50, comment: 'NAME' }], [:notes, :text, { limit: 55, comment: 'NOTES' }], - [:no_comment, :text, { limit: 20, comment: nil }] + [:no_comment, :text, { limit: 20, comment: nil }], + [:location, :geometry_collection, { limit: nil, comment: nil }] ] when_called_with with_comment: 'yes', @@ -958,6 +959,7 @@ def self.when_called_with(options = {}) # name(NAME) :string(50) not null # notes(NOTES) :text(55) not null # no_comment :text(20) not null + # location :geometry_collect not null # EOS From 681d53720894163a095ef27dcd0b59deb0ef08e0 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Sun, 16 Jun 2019 14:45:45 -0700 Subject: [PATCH 05/27] Update .travis.yml to unblock Ruby 2.2 builds (#628) * Update Ruby 2.2.7 to 2.2.10 There are 3 patch versions of security and vulnerability fixes and 2.2.7 was released back in March 28 2017. * Use older version of RubyGems for Ruby 2.2 The current build tries to update to RubyGems 3. This currently fails for Ruby 2.2 because RubyGems 3.0.0 drops support for Ruby 2.2.X. This change should support Ruby 2.2 by explicitly installing RubyGems 2.7 after failing to find a compatible version of 3. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 75b0d9acb..0ecc68d6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: ruby rvm: -- 2.2.7 +- 2.2.10 - 2.3.8 - 2.4.6 - 2.5.5 @@ -16,7 +16,7 @@ matrix: - rvm: ruby-head before_install: -- gem update --system +- gem update --system || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems) - gem update bundler script: From 5ac56e4740906a74f302b92b0c350979526e4f4b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" Date: Sun, 16 Jun 2019 14:57:21 -0700 Subject: [PATCH 06/27] Update rubocop requirement from ~> 0.67.2 to ~> 0.68.1 (#616) * Update rubocop requirement from ~> 0.67.2 to ~> 0.68.1 Updates the requirements on [rubocop](https://github.com/rubocop-hq/rubocop) to permit the latest version. - [Release notes](https://github.com/rubocop-hq/rubocop/releases) - [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.67.2...v0.68.1) * Rerun rubocop --auto-gen-config The cop Layout/IndexHash was renamed to Layout/IndentFirstHashElement causing CI to fail. By rerunning the config generator this updates the correct cop name so that Rubocop no longer fails in CI. --- .rubocop.yml | 3 ++- .rubocop_todo.yml | 35 ++++++++++++++--------------------- Gemfile | 2 +- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index c58fbed4c..d3c8146d3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,5 @@ -inherit_from: ./.rubocop_todo.yml +inherit_from: + - .rubocop_todo.yml AllCops: Exclude: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 578f1b345..552b76072 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2019-03-07 18:25:02 -0800 using RuboCop version 0.65.0. +# on 2019-06-16 12:01:03 -0700 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 @@ -51,7 +51,7 @@ Layout/AlignArray: Exclude: - 'spec/annotate/annotate_models_spec.rb' -# Offense count: 103 +# Offense count: 104 # Cop supports --auto-correct. # Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table @@ -149,7 +149,7 @@ Layout/EmptyLinesAroundExceptionHandlingKeywords: # Offense count: 24 # Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment. +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. Layout/ExtraSpacing: Exclude: - 'Guardfile' @@ -170,7 +170,7 @@ Layout/ExtraSpacing: # Cop supports --auto-correct. # Configuration parameters: IndentationWidth. # SupportedStyles: special_inside_parentheses, consistent, align_braces -Layout/IndentHash: +Layout/IndentFirstHashElement: EnforcedStyle: consistent # Offense count: 54 @@ -247,7 +247,7 @@ Layout/SpaceAroundKeyword: - 'spec/integration/rails_4.2.0/Gemfile' - 'spec/integration/standalone/Gemfile' -# Offense count: 4 +# Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: AllowForAlignment. Layout/SpaceAroundOperators: @@ -419,15 +419,15 @@ Lint/UnusedBlockArgument: Exclude: - 'bin/annotate' -# Offense count: 18 +# Offense count: 19 Metrics/AbcSize: - Max: 139 + Max: 138 -# Offense count: 29 +# Offense count: 27 # Configuration parameters: CountComments, ExcludedMethods. # ExcludedMethods: refine Metrics/BlockLength: - Max: 1140 + Max: 244 # Offense count: 1 # Configuration parameters: CountBlocks. @@ -475,14 +475,6 @@ Naming/UncommunicativeMethodParamName: Exclude: - 'Rakefile' -# Offense count: 4 -# Cop supports --auto-correct. -Performance/RegexpMatch: - Exclude: - - 'lib/annotate/annotate_models.rb' - - 'lib/annotate/annotate_routes.rb' - - 'spec/integration/rails_2.3_with_bundler/config/boot.rb' - # Offense count: 1 # Configuration parameters: EnforcedStyle. # SupportedStyles: inline, group @@ -688,7 +680,7 @@ Style/NestedParenthesizedCalls: Style/NumericLiterals: MinDigits: 15 -# Offense count: 2 +# Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. # SupportedStyles: predicate, comparison @@ -809,7 +801,7 @@ Style/StderrPuts: - 'lib/annotate/annotate_models.rb' - 'spec/integration/rails_2.3_with_bundler/config/boot.rb' -# Offense count: 240 +# Offense count: 243 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -867,8 +859,9 @@ Style/UnneededPercentQ: - 'annotate.gemspec' - 'spec/integration/rails_2.3_with_bundler/config/boot.rb' -# Offense count: 424 -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# Offense count: 431 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: Max: 276 diff --git a/Gemfile b/Gemfile index ccfc11bc9..cd3dae1be 100644 --- a/Gemfile +++ b/Gemfile @@ -19,7 +19,7 @@ group :development, :test do gem 'guard-rspec', require: false gem 'rspec', require: false - gem 'rubocop', '~> 0.67.2', require: false unless RUBY_VERSION =~ /^1.8/ + gem 'rubocop', '~> 0.68.1', require: false unless RUBY_VERSION =~ /^1.8/ gem 'simplecov', require: false gem 'terminal-notifier-guard', require: false From 46d2d63f19b00b3c9fbee3b0f396ee0591929034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AD=E3=81=9A?= <39144575+wonda-tea-coffee@users.noreply.github.com> Date: Mon, 1 Jul 2019 16:53:30 +0900 Subject: [PATCH 07/27] Fix BigDecimal.new (#634) `BigDecimal.new` is deprecated in future version of Ruby in favor of using `BigDecimal(...)`. --- spec/annotate/annotate_models_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/annotate/annotate_models_spec.rb b/spec/annotate/annotate_models_spec.rb index f23cad117..d7705c888 100644 --- a/spec/annotate/annotate_models_spec.rb +++ b/spec/annotate/annotate_models_spec.rb @@ -70,8 +70,8 @@ def mock_column(name, type, options = {}) it { expect(AnnotateModels.quote(25)).to eql('25') } it { expect(AnnotateModels.quote(25.6)).to eql('25.6') } it { expect(AnnotateModels.quote(1e-20)).to eql('1.0e-20') } - it { expect(AnnotateModels.quote(BigDecimal.new('1.2'))).to eql('1.2') } - it { expect(AnnotateModels.quote([BigDecimal.new('1.2')])).to eql(['1.2']) } + it { expect(AnnotateModels.quote(BigDecimal('1.2'))).to eql('1.2') } + it { expect(AnnotateModels.quote([BigDecimal('1.2')])).to eql(['1.2']) } describe '#parse_options' do let(:options) do From f612f8ad785b2a44cab88ff3836ff20b17e6e21a Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Sun, 7 Jul 2019 14:26:33 -0700 Subject: [PATCH 08/27] Add tests for the CLI (#635) Currently there's no test coverage on CLI. This adds tests for a new class Parser which will replace the command line options currently in bin/annotate. The technical direction I'm planning to go is to remove ENV variables completely and to have things passed into as arguments. Will be adding deprecation warnings in 3.0 and then deprecate ENV variables completely in 3.1. Deprecation warnings will be non-blocking in 3.0 when an ENV variable is set and an argument isn't passed in, and will becoming blocking in 3.1. --- bin/annotate | 196 +------------ lib/annotate/parser.rb | 230 +++++++++++++++ spec/annotate/parser_spec.rb | 531 +++++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 1 + 4 files changed, 768 insertions(+), 190 deletions(-) create mode 100644 lib/annotate/parser.rb create mode 100644 spec/annotate/parser_spec.rb diff --git a/bin/annotate b/bin/annotate index 2f27d5d73..a27c17515 100755 --- a/bin/annotate +++ b/bin/annotate @@ -14,203 +14,19 @@ end here = File.expand_path(File.dirname __FILE__) $LOAD_PATH << "#{here}/../lib" -require 'optparse' require 'annotate' -Annotate.bootstrap_rake - -has_set_position = {} -target_action = :do_annotations -positions = %w(before top after bottom) - -OptionParser.new do |opts| - opts.banner = 'Usage: annotate [options] [model_file]*' - - opts.on('-d', '--delete', 'Remove annotations from all model files or the routes.rb file') do - target_action = :remove_annotations - end - - opts.on('-p', '--position [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |p| - ENV['position'] = p - %w(position_in_class position_in_factory position_in_fixture position_in_test position_in_routes position_in_serializer).each do |key| - ENV[key] = p unless has_set_position[key] - end - end - - opts.on('--pc', '--position-in-class [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the model file') do |p| - ENV['position_in_class'] = p - has_set_position['position_in_class'] = true - end - - opts.on('--pf', '--position-in-factory [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of any factory files') do |p| - ENV['position_in_factory'] = p - has_set_position['position_in_factory'] = true - end - - opts.on('--px', '--position-in-fixture [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of any fixture files') do |p| - ENV['position_in_fixture'] = p - has_set_position['position_in_fixture'] = true - end - - opts.on('--pt', '--position-in-test [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of any test files') do |p| - ENV['position_in_test'] = p - has_set_position['position_in_test'] = true - end - - opts.on('--pr', '--position-in-routes [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the routes.rb file') do |p| - ENV['position_in_routes'] = p - has_set_position['position_in_routes'] = true - end - - opts.on('--ps', '--position-in-serializer [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the serializer files') do |p| - ENV['position_in_serializer'] = p - has_set_position['position_in_serializer'] = true - end - - opts.on('--w', '--wrapper STR', 'Wrap annotation with the text passed as parameter.', - 'If --w option is used, the same text will be used as opening and closing') do |p| - ENV['wrapper'] = p - end - - opts.on('--wo', '--wrapper-open STR', 'Annotation wrapper opening.') do |p| - ENV['wrapper_open'] = p - end - - opts.on('--wc', '--wrapper-close STR', 'Annotation wrapper closing') do |p| - ENV['wrapper_close'] = p - end - - opts.on('-r', '--routes', "Annotate routes.rb with the output of 'rake routes'") do - ENV['routes'] = 'true' - end - - opts.on('-a', '--active-admin', 'Annotate active_admin models') do - ENV['active_admin'] = 'true' - end - - opts.on('-v', '--version', 'Show the current version of this gem') do - puts "annotate v#{Annotate.version}"; exit - end - - opts.on('-m', '--show-migration', 'Include the migration version number in the annotation') do - ENV['include_version'] = 'yes' - end - - opts.on('-k', '--show-foreign-keys', - "List the table's foreign key constraints in the annotation") do - ENV['show_foreign_keys'] = 'yes' - end +require 'annotate/parser' - opts.on('--ck', - '--complete-foreign-keys', 'Complete foreign key names in the annotation') do - ENV['show_foreign_keys'] = 'yes' - ENV['show_complete_foreign_keys'] = 'yes' - end - - opts.on('-i', '--show-indexes', - "List the table's database indexes in the annotation") do - ENV['show_indexes'] = 'yes' - end - - opts.on('-s', '--simple-indexes', - "Concat the column's related indexes in the annotation") do - ENV['simple_indexes'] = 'yes' - end - - opts.on('--model-dir dir', - "Annotate model files stored in dir rather than app/models, separate multiple dirs with commas") do |dir| - ENV['model_dir'] = dir - end - - opts.on('--root-dir dir', - "Annotate files stored within root dir projects, separate multiple dirs with commas") do |dir| - ENV['root_dir'] = dir - end - - opts.on('--ignore-model-subdirects', - "Ignore subdirectories of the models directory") do |dir| - ENV['ignore_model_sub_dir'] = 'yes' - end - - opts.on('--sort', - "Sort columns alphabetically, rather than in creation order") do |dir| - ENV['sort'] = 'yes' - end - - opts.on('--classified-sort', - "Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns") do |dir| - ENV['classified_sort'] = 'yes' - end - - opts.on('-R', '--require path', - "Additional file to require before loading models, may be used multiple times") do |path| - if !ENV['require'].blank? - ENV['require'] = ENV['require'] + ",#{path}" - else - ENV['require'] = path - end - end - - opts.on('-e', '--exclude [tests,fixtures,factories,serializers]', Array, "Do not annotate fixtures, test files, factories, and/or serializers") do |exclusions| - exclusions ||= %w(tests fixtures factories) - exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = 'yes' } - end - - opts.on('-f', '--format [bare|rdoc|markdown]', %w(bare rdoc markdown), 'Render Schema Infomation as plain/RDoc/Markdown') do |fmt| - ENV["format_#{fmt}"] = 'yes' - end - - opts.on('--force', 'Force new annotations even if there are no changes.') do |force| - ENV['force'] = 'yes' - end - - opts.on('--frozen', 'Do not allow to change annotations. Exits non-zero if there are going to be changes to files.') do - ENV['frozen'] = 'yes' - end - - opts.on('--timestamp', 'Include timestamp in (routes) annotation') do - ENV['timestamp'] = 'true' - end - - opts.on('--trace', 'If unable to annotate a file, print the full stack trace, not just the exception message.') do |value| - ENV['trace'] = 'yes' - end - - opts.on('-I', '--ignore-columns REGEX', "don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`") do |regex| - ENV['ignore_columns'] = regex - end - - opts.on('--ignore-routes REGEX', "don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'`") do |regex| - ENV['ignore_routes'] = regex - end - - opts.on('--hide-limit-column-types VALUES', "don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values| - ENV['hide_limit_column_types'] = "#{values}" - end - - opts.on('--hide-default-column-types VALUES', "don't show default for given column types, separated by commas (i.e., `json,jsonb,hstore`)") do |values| - ENV['hide_default_column_types'] = "#{values}" - end +Annotate.bootstrap_rake - opts.on('--ignore-unknown-models', "don't display warnings for bad model files") do |values| - ENV['ignore_unknown_models'] = 'true' - end +options_result = Annotate::Parser.parse(ARGV) - opts.on('--with-comment', "include database comments in model annotations") do |values| - ENV['with_comment'] = 'true' - end -end.parse! +exit if options_result[:exit] options = Annotate.setup_options( is_rake: ENV['is_rake'] && !ENV['is_rake'].empty? ) Annotate.eager_load(options) if Annotate.include_models? -AnnotateModels.send(target_action, options) if Annotate.include_models? -AnnotateRoutes.send(target_action, options) if Annotate.include_routes? +AnnotateModels.send(options_result[:target_action], options) if Annotate.include_models? +AnnotateRoutes.send(options_result[:target_action], options) if Annotate.include_routes? diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb new file mode 100644 index 000000000..2b391ff66 --- /dev/null +++ b/lib/annotate/parser.rb @@ -0,0 +1,230 @@ +require 'optparse' + +module Annotate + # Class for handling command line arguments + class Parser # rubocop:disable Metrics/ClassLength + def self.parse(args) + new(args).parse + end + + attr_reader :args + + ANNOTATION_POSITIONS = %w[before top after bottom].freeze + FILE_TYPE_POSITIONS = %w[position_in_class position_in_factory position_in_fixture position_in_test position_in_routes position_in_serializer].freeze + EXCLUSION_LIST = %w[tests fixtures factories serializers].freeze + FORMAT_TYPES = %w[bare rdoc markdown].freeze + + def initialize(args) + @args = args + end + + def parse + options = default_options + + parser(options).parse!(args) + + options + end + + private + + def parser(options) # rubocop:disable Metrics/MethodLength + has_set_position = {} + positions = ANNOTATION_POSITIONS + + OptionParser.new do |opts| + opts.banner = 'Usage: annotate [options] [model_file]*' + + opts.on('-d', '--delete', 'Remove annotations from all model files or the routes.rb file') do + options[:target_action] = :remove_annotations + end + + opts.on('-p', '--position [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |p| + ENV['position'] = p + + FILE_TYPE_POSITIONS.each do |key| + ENV[key] = p unless has_set_position[key] + end + end + + opts.on('--pc', '--position-in-class [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the model file') do |p| + ENV['position_in_class'] = p + has_set_position['position_in_class'] = true + end + + opts.on('--pf', '--position-in-factory [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of any factory files') do |p| + ENV['position_in_factory'] = p + has_set_position['position_in_factory'] = true + end + + opts.on('--px', '--position-in-fixture [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of any fixture files') do |p| + ENV['position_in_fixture'] = p + has_set_position['position_in_fixture'] = true + end + + opts.on('--pt', '--position-in-test [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of any test files') do |p| + ENV['position_in_test'] = p + has_set_position['position_in_test'] = true + end + + opts.on('--pr', '--position-in-routes [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the routes.rb file') do |p| + ENV['position_in_routes'] = p + has_set_position['position_in_routes'] = true + end + + opts.on('--ps', '--position-in-serializer [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the serializer files') do |p| + ENV['position_in_serializer'] = p + has_set_position['position_in_serializer'] = true + end + + opts.on('--w', '--wrapper STR', 'Wrap annotation with the text passed as parameter.', + 'If --w option is used, the same text will be used as opening and closing') do |p| + ENV['wrapper'] = p + end + + opts.on('--wo', '--wrapper-open STR', 'Annotation wrapper opening.') do |p| + ENV['wrapper_open'] = p + end + + opts.on('--wc', '--wrapper-close STR', 'Annotation wrapper closing') do |p| + ENV['wrapper_close'] = p + end + + opts.on('-r', '--routes', "Annotate routes.rb with the output of 'rake routes'") do + ENV['routes'] = 'true' + end + + opts.on('-a', '--active-admin', 'Annotate active_admin models') do + ENV['active_admin'] = 'true' + end + + opts.on('-v', '--version', 'Show the current version of this gem') do + puts "annotate v#{Annotate.version}" + options[:exit] = true + end + + opts.on('-m', '--show-migration', 'Include the migration version number in the annotation') do + ENV['include_version'] = 'yes' + end + + opts.on('-k', '--show-foreign-keys', + "List the table's foreign key constraints in the annotation") do + ENV['show_foreign_keys'] = 'yes' + end + + opts.on('--ck', + '--complete-foreign-keys', 'Complete foreign key names in the annotation') do + ENV['show_foreign_keys'] = 'yes' + ENV['show_complete_foreign_keys'] = 'yes' + end + + opts.on('-i', '--show-indexes', + "List the table's database indexes in the annotation") do + ENV['show_indexes'] = 'yes' + end + + opts.on('-s', '--simple-indexes', + "Concat the column's related indexes in the annotation") do + ENV['simple_indexes'] = 'yes' + end + + opts.on('--model-dir dir', + "Annotate model files stored in dir rather than app/models, separate multiple dirs with commas") do |dir| + ENV['model_dir'] = dir + end + + opts.on('--root-dir dir', + "Annotate files stored within root dir projects, separate multiple dirs with commas") do |dir| + ENV['root_dir'] = dir + end + + opts.on('--ignore-model-subdirects', + "Ignore subdirectories of the models directory") do |_dir| + ENV['ignore_model_sub_dir'] = 'yes' + end + + opts.on('--sort', + "Sort columns alphabetically, rather than in creation order") do |_dir| + ENV['sort'] = 'yes' + end + + opts.on('--classified-sort', + "Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns") do |_dir| + ENV['classified_sort'] = 'yes' + end + + opts.on('-R', '--require path', + "Additional file to require before loading models, may be used multiple times") do |path| + ENV['require'] = if !ENV['require'].blank? + ENV['require'] + ",#{path}" + else + path + end + end + + opts.on('-e', '--exclude [tests,fixtures,factories,serializers]', Array, "Do not annotate fixtures, test files, factories, and/or serializers") do |exclusions| + exclusions ||= EXCLUSION_LIST + exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = 'yes' } + end + + opts.on('-f', '--format [bare|rdoc|markdown]', FORMAT_TYPES, 'Render Schema Infomation as plain/RDoc/Markdown') do |fmt| + ENV["format_#{fmt}"] = 'yes' + end + + opts.on('--force', 'Force new annotations even if there are no changes.') do |_force| + ENV['force'] = 'yes' + end + + opts.on('--frozen', 'Do not allow to change annotations. Exits non-zero if there are going to be changes to files.') do + ENV['frozen'] = 'yes' + end + + opts.on('--timestamp', 'Include timestamp in (routes) annotation') do + ENV['timestamp'] = 'true' + end + + opts.on('--trace', 'If unable to annotate a file, print the full stack trace, not just the exception message.') do |_value| + ENV['trace'] = 'yes' + end + + opts.on('-I', '--ignore-columns REGEX', "don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`") do |regex| + ENV['ignore_columns'] = regex + end + + opts.on('--ignore-routes REGEX', "don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'`") do |regex| + ENV['ignore_routes'] = regex + end + + opts.on('--hide-limit-column-types VALUES', "don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values| + ENV['hide_limit_column_types'] = values.to_s + end + + opts.on('--hide-default-column-types VALUES', "don't show default for given column types, separated by commas (i.e., `json,jsonb,hstore`)") do |values| + ENV['hide_default_column_types'] = values.to_s + end + + opts.on('--ignore-unknown-models', "don't display warnings for bad model files") do |_values| + ENV['ignore_unknown_models'] = 'true' + end + + opts.on('--with-comment', "include database comments in model annotations") do |_values| + ENV['with_comment'] = 'true' + end + end + end + + def default_options + { + target_action: :do_annotations, + exit: false + } + end + end +end diff --git a/spec/annotate/parser_spec.rb b/spec/annotate/parser_spec.rb new file mode 100644 index 000000000..7ece2903a --- /dev/null +++ b/spec/annotate/parser_spec.rb @@ -0,0 +1,531 @@ +require File.dirname(__FILE__) + '/../spec_helper.rb' + +module Annotate # rubocop:disable Metrics/ModuleLength + describe Parser do # rubocop:disable Metrics/BlockLength + before(:example) do + ENV.clear + end + + context 'when given empty args' do + it 'returns an options hash with defaults' do + result = Parser.parse([]) + expect(result).to be_a(Hash) + expect(result).to include(target_action: :do_annotations) + end + end + + %w[-d --delete].each do |option| + describe option do + it 'sets target_action to :remove_annotations' do + result = Parser.parse([option]) + expect(result).to include(target_action: :remove_annotations) + end + end + end + + %w[-p --position].each do |option| + describe option do + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying #{position}" do + it "#{position} position is an option" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(Parser::ANNOTATION_POSITIONS).to include(position) + end + + it "sets ENV['position'] to be position" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + + expect(ENV).to have_received(:[]=).with('position', position) + end + + it 'sets the value in ENV for the different file types' do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + + Parser::FILE_TYPE_POSITIONS.each do |file_type| + expect(ENV).to have_received(:[]=).with(file_type, position) + end + end + end + end + end + end + + context 'when position_in_class is set to top' do + context 'and when position is a different value' do + it 'does not override' do + other_commands = %w[--pc top] + position_command = %w[-p bottom] + options = other_commands + position_command + + Parser.parse(options) + expect(ENV['position_in_class']).to eq('top') + expect(ENV['position']).to eq('bottom') + end + end + end + + %w[--pc --position-in-class].each do |option| + describe option do + let(:env_key) { 'position_in_class' } + + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying '#{position}'" do + it "sets the ENV variable to '#{position}'" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(ENV).to have_received(:[]=).with(env_key, position) + end + end + end + end + end + + %w[--pf --position-in-factory].each do |option| + describe option do + let(:env_key) { 'position_in_factory' } + + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying #{position}" do + it "sets the ENV variable to #{position}" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(ENV).to have_received(:[]=).with(env_key, position) + end + end + end + end + end + + %w[--px --position-in-fixture].each do |option| + describe option do + let(:env_key) { 'position_in_fixture' } + + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying #{position}" do + it "sets the ENV variable to #{position}" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(ENV).to have_received(:[]=).with(env_key, position) + end + end + end + end + end + + %w[--pt --position-in-test].each do |option| + describe option do + let(:env_key) { 'position_in_test' } + + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying #{position}" do + it "sets the ENV variable to #{position}" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(ENV).to have_received(:[]=).with(env_key, position) + end + end + end + end + end + + %w[--pr --position-in-routes].each do |option| + describe option do + let(:env_key) { 'position_in_routes' } + + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying #{position}" do + it "sets the ENV variable to #{position}" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(ENV).to have_received(:[]=).with(env_key, position) + end + end + end + end + end + + %w[--ps --position-in-serializer].each do |option| + describe option do + let(:env_key) { 'position_in_serializer' } + + Parser::ANNOTATION_POSITIONS.each do |position| + context "when specifying #{position}" do + it "sets the ENV variable to #{position}" do + allow(ENV).to receive(:[]=) + Parser.parse([option, position]) + expect(ENV).to have_received(:[]=).with(env_key, position) + end + end + end + end + end + + %w[--w --wrapper].each do |option| + describe option do + let(:env_key) { 'wrapper' } + let(:set_value) { 'STR' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, set_value]) + end + end + end + + %w[--wo --wrapper-open].each do |option| + describe option do + let(:env_key) { 'wrapper_open' } + let(:set_value) { 'STR' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, set_value]) + end + end + end + + %w[--wc --wrapper-close].each do |option| + describe option do + let(:env_key) { 'wrapper_close' } + let(:set_value) { 'STR' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, set_value]) + end + end + end + + %w[-r --routes].each do |option| + describe option do + let(:env_key) { 'routes' } + let(:set_value) { 'true' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + + %w[-a --active-admin].each do |option| + describe option do + let(:env_key) { 'active_admin' } + let(:set_value) { 'true' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + + %w[-v --version].each do |option| + describe option do + it 'sets the ENV variable' do + expect { Parser.parse([option]) }.to output("annotate v#{Annotate.version}\n").to_stdout + expect(Parser.parse([option])).to include(exit: true) + end + end + end + + %w[-m --show-migration].each do |option| + describe option do + let(:env_key) { 'include_version' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + + %w[-k --show-foreign-keys].each do |option| + describe option do + let(:env_key) { 'show_foreign_keys' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + + %w[--ck --complete-foreign-keys].each do |option| + describe option do + it 'sets the ENV variable' do + allow(ENV).to receive(:[]=) + Parser.parse([option]) + + expect(ENV).to have_received(:[]=).with('show_foreign_keys', 'yes') + expect(ENV).to have_received(:[]=).with('show_complete_foreign_keys', 'yes') + end + end + end + + %w[-i --show-indexes].each do |option| + describe option do + let(:env_key) { 'show_indexes' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + + %w[-s --simple-indexes].each do |option| + describe option do + let(:env_key) { 'simple_indexes' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + + describe '--model-dir' do + let(:option) { '--model-dir' } + let(:env_key) { 'model_dir' } + let(:set_value) { 'some_dir/' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, set_value]) + end + end + + describe '--root-dir' do + let(:option) { '--root-dir' } + let(:env_key) { 'root_dir' } + let(:set_value) { 'some_dir/' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, set_value]) + end + end + + describe '--ignore-model-subdirects' do + let(:option) { '--ignore-model-subdirects' } + let(:env_key) { 'ignore_model_sub_dir' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + describe '--sort' do + let(:option) { '--sort' } + let(:env_key) { 'sort' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + describe '--classified-sort' do + let(:option) { '--classified-sort' } + let(:env_key) { 'classified_sort' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + %w[-R --require].each do |option| + describe option do + let(:env_key) { 'require' } + let(:set_value) { 'another_dir' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, set_value]) + end + + context "when ENV['require'] is already set" do + let(:preset_require_value) { 'some_dir/' } + it "appends the path to ENV['require']" do + allow(ENV).to receive(:[]).and_return(preset_require_value) + expect(ENV).to receive(:[]=).with(env_key, "#{preset_require_value},#{set_value}") + Parser.parse([option, set_value]) + end + end + end + end + + describe 'Parser::EXCLUSION_LIST' do + it "has 'tests'" do + expect(Parser::EXCLUSION_LIST).to include('tests') + end + + it "has 'fixtures'" do + expect(Parser::EXCLUSION_LIST).to include('fixtures') + end + + it "has 'factories'" do + expect(Parser::EXCLUSION_LIST).to include('factories') + end + + it "has 'serializers'" do + expect(Parser::EXCLUSION_LIST).to include('serializers') + end + end + + %w[-e --exclude].each do |option| + describe option do + let(:set_value) { 'yes' } + + it "sets the exclusion ENV variables for 'tests', 'fixtures', 'factories', and 'serializers'" do + allow(ENV).to receive(:[]=) + Parser.parse([option]) + + expect(ENV).to have_received(:[]=).with('exclude_tests', set_value) + expect(ENV).to have_received(:[]=).with('exclude_fixtures', set_value) + expect(ENV).to have_received(:[]=).with('exclude_factories', set_value) + expect(ENV).to have_received(:[]=).with('exclude_serializers', set_value) + end + + context 'when a type is passed in' do + let(:exclusions) { "tests" } + + it "sets the exclusion ENV variable for 'tests' only" do + expect(ENV).to receive(:[]=).with('exclude_tests', set_value) + Parser.parse([option, exclusions]) + end + end + + context 'when two types are passed in' do + let(:exclusions) { "tests,fixtures" } + + it "sets the exclusion ENV variable for 'tests' and 'fixtures'" do + allow(ENV).to receive(:[]=) + Parser.parse([option, exclusions]) + expect(ENV).to have_received(:[]=).with('exclude_tests', set_value) + expect(ENV).to have_received(:[]=).with('exclude_fixtures', set_value) + end + end + end + end + + %w[-f --format].each do |option| + describe option do + Parser::FORMAT_TYPES.each do |format_type| + context "when passing in format type '#{format_type}'" do + let(:env_key) { "format_#{format_type}" } + let(:set_value) { 'yes' } + + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option, format_type]) + end + end + end + end + end + + describe '--force' do + let(:option) { '--force' } + let(:env_key) { 'force' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + describe '--frozen' do + let(:option) { '--frozen' } + let(:env_key) { 'frozen' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + describe '--timestamp' do + let(:option) { '--timestamp' } + let(:env_key) { 'timestamp' } + let(:set_value) { 'true' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + describe '--trace' do + let(:option) { '--trace' } + let(:env_key) { 'trace' } + let(:set_value) { 'yes' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + %w[-I --ignore-columns].each do |option| + describe option do + let(:env_key) { 'ignore_columns' } + let(:regex) { '^(id|updated_at|created_at)' } + + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, regex) + Parser.parse([option, regex]) + end + end + end + + describe '--ignore-routes' do + let(:option) { '--ignore-routes' } + let(:env_key) { 'ignore_routes' } + let(:regex) { '(mobile|resque|pghero)' } + + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, regex) + Parser.parse([option, regex]) + end + end + + describe '--hide-limit-column-types' do + let(:option) { '--hide-limit-column-types' } + let(:env_key) { 'hide_limit_column_types' } + let(:values) { 'integer,boolean,text' } + + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, values) + Parser.parse([option, values]) + end + end + + describe '--hide-default-column-types' do + let(:option) { '--hide-default-column-types' } + let(:env_key) { 'hide_default_column_types' } + let(:values) { 'json,jsonb,hstore' } + + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, values) + Parser.parse([option, values]) + end + end + + describe '--ignore-unknown-models' do + let(:option) { '--ignore-unknown-models' } + let(:env_key) { 'ignore_unknown_models' } + let(:set_value) { 'true' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + + describe '--with-comment' do + let(:option) { '--with-comment' } + let(:env_key) { 'with_comment' } + let(:set_value) { 'true' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6362aeec4..2763a91be 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -28,6 +28,7 @@ require 'active_support/core_ext/class/subclasses' require 'active_support/core_ext/string/inflections' require 'annotate' +require 'annotate/parser' require 'byebug' module Annotate From f95913ba1b9c4c4c1fe357ca6160f02c955a6a38 Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 10 Jul 2019 13:21:22 -0700 Subject: [PATCH 09/27] Add option for additional file patterns (#633) This PR adds an option named `additional_file_patterns`. You can specify custom path patterns (including globs) that the gem will use to annotate. For example, I used it like this on a project: ```ruby Annotate.set_defaults( 'additional_file_patterns' => [ File.join(Rails.application.root, 'app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb'), File.join(Rails.application.root, 'spec/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb') ], ... ) ``` This makes it possible to have files nested under a directory which corresponds to the model. I believe this fixes #594. --- lib/annotate.rb | 3 +- lib/annotate/annotate_models.rb | 30 +++++-- .../templates/auto_annotate_models.rake | 83 ++++++++++--------- spec/annotate/annotate_models_spec.rb | 82 ++++++++++++++++++ 4 files changed, 149 insertions(+), 49 deletions(-) diff --git a/lib/annotate.rb b/lib/annotate.rb index 27e585773..db223a333 100644 --- a/lib/annotate.rb +++ b/lib/annotate.rb @@ -36,7 +36,7 @@ module Annotate :exclude_sti_subclasses, :ignore_unknown_models, :with_comment ].freeze OTHER_OPTIONS = [ - :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close, + :additional_file_patterns, :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close, :wrapper, :routes, :hide_limit_column_types, :hide_default_column_types, :ignore_routes, :active_admin ].freeze @@ -88,6 +88,7 @@ def self.setup_options(options = {}) options[key] = !ENV[key.to_s].blank? ? ENV[key.to_s].split(',') : [] end + options[:additional_file_patterns] ||= [] options[:model_dir] = ['app/models'] if options[:model_dir].empty? options[:wrapper_open] ||= options[:wrapper] diff --git a/lib/annotate/annotate_models.rb b/lib/annotate/annotate_models.rb index 1d64c383d..b2cf7453d 100644 --- a/lib/annotate/annotate_models.rb +++ b/lib/annotate/annotate_models.rb @@ -159,13 +159,15 @@ def serialize_files(root_directory) ] end - def files_by_pattern(root_directory, pattern_type) + def files_by_pattern(root_directory, pattern_type, options) case pattern_type when 'test' then test_files(root_directory) when 'fixture' then fixture_files(root_directory) when 'scaffold' then scaffold_files(root_directory) when 'factory' then factory_files(root_directory) when 'serializer' then serialize_files(root_directory) + when 'additional_file_patterns' + [options[:additional_file_patterns] || []].flatten when 'controller' [File.join(root_directory, CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")] when 'admin' @@ -177,14 +179,20 @@ def files_by_pattern(root_directory, pattern_type) end end - def get_patterns(pattern_types = []) + def get_patterns(options, pattern_types = []) current_patterns = [] root_dir.each do |root_directory| Array(pattern_types).each do |pattern_type| - current_patterns += files_by_pattern(root_directory, pattern_type) + patterns = files_by_pattern(root_directory, pattern_type, options) + + current_patterns += if pattern_type.to_sym == :additional_file_patterns + patterns + else + patterns.map { |p| p.sub(/^[\/]*/, '') } + end end end - current_patterns.map { |p| p.sub(/^[\/]*/, '') } + current_patterns end # Simple quoting for the default column value @@ -581,8 +589,9 @@ def remove_annotation_of_file(file_name, options = {}) end def matched_types(options) - types = MATCHED_TYPES + types = MATCHED_TYPES.dup types << 'admin' if options[:active_admin] =~ TRUE_RE && !types.include?('admin') + types << 'additional_file_patterns' if options[:additional_file_patterns].present? types end @@ -634,8 +643,11 @@ def annotate(klass, file, header, options = {}) end next if options[exclusion_key] - get_patterns(key) + + get_patterns(options, key) .map { |f| resolve_filename(f, model_name, table_name) } + .map { |f| expand_glob_into_files(f) } + .flatten .each do |f| if annotate_one_file(f, info, position_key, options_with_position(options, position_key)) annotated << f @@ -793,6 +805,10 @@ def do_annotations(options = {}) end end + def expand_glob_into_files(glob) + Dir.glob(glob) + end + def annotate_model_file(annotated, file, header, options) begin return false if /#{SKIP_ANNOTATION_PREFIX}.*/ =~ (File.exist?(file) ? File.read(file) : '') @@ -830,7 +846,7 @@ def remove_annotations(options = {}) model_file_name = file deannotated_klass = true if remove_annotation_of_file(model_file_name, options) - get_patterns(matched_types(options)) + get_patterns(options, matched_types(options)) .map { |f| resolve_filename(f, model_name, table_name) } .each do |f| if File.exist?(f) diff --git a/lib/generators/annotate/templates/auto_annotate_models.rake b/lib/generators/annotate/templates/auto_annotate_models.rake index eea2aa859..911c44211 100644 --- a/lib/generators/annotate/templates/auto_annotate_models.rake +++ b/lib/generators/annotate/templates/auto_annotate_models.rake @@ -7,47 +7,48 @@ if Rails.env.development? # You can override any of these by setting an environment variable of the # same name. Annotate.set_defaults( - 'routes' => 'false', - 'position_in_routes' => 'before', - 'position_in_class' => 'before', - 'position_in_test' => 'before', - 'position_in_fixture' => 'before', - 'position_in_factory' => 'before', - 'position_in_serializer' => 'before', - 'show_foreign_keys' => 'true', - 'show_complete_foreign_keys' => 'false', - 'show_indexes' => 'true', - 'simple_indexes' => 'false', - 'model_dir' => 'app/models', - 'root_dir' => '', - 'include_version' => 'false', - 'require' => '', - 'exclude_tests' => 'false', - 'exclude_fixtures' => 'false', - 'exclude_factories' => 'false', - 'exclude_serializers' => 'false', - 'exclude_scaffolds' => 'true', - 'exclude_controllers' => 'true', - 'exclude_helpers' => 'true', - 'exclude_sti_subclasses' => 'false', - 'ignore_model_sub_dir' => 'false', - 'ignore_columns' => nil, - 'ignore_routes' => nil, - 'ignore_unknown_models' => 'false', - 'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>', - 'hide_default_column_types' => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>', - 'skip_on_db_migrate' => 'false', - 'format_bare' => 'true', - 'format_rdoc' => 'false', - 'format_markdown' => 'false', - 'sort' => 'false', - 'force' => 'false', - 'frozen' => 'false', - 'classified_sort' => 'true', - 'trace' => 'false', - 'wrapper_open' => nil, - 'wrapper_close' => nil, - 'with_comment' => 'true' + 'additional_file_patterns' => [], + 'routes' => 'false', + 'position_in_routes' => 'before', + 'position_in_class' => 'before', + 'position_in_test' => 'before', + 'position_in_fixture' => 'before', + 'position_in_factory' => 'before', + 'position_in_serializer' => 'before', + 'show_foreign_keys' => 'true', + 'show_complete_foreign_keys' => 'false', + 'show_indexes' => 'true', + 'simple_indexes' => 'false', + 'model_dir' => 'app/models', + 'root_dir' => '', + 'include_version' => 'false', + 'require' => '', + 'exclude_tests' => 'false', + 'exclude_fixtures' => 'false', + 'exclude_factories' => 'false', + 'exclude_serializers' => 'false', + 'exclude_scaffolds' => 'true', + 'exclude_controllers' => 'true', + 'exclude_helpers' => 'true', + 'exclude_sti_subclasses' => 'false', + 'ignore_model_sub_dir' => 'false', + 'ignore_columns' => nil, + 'ignore_routes' => nil, + 'ignore_unknown_models' => 'false', + 'hide_limit_column_types' => '<%= AnnotateModels::NO_LIMIT_COL_TYPES.join(",") %>', + 'hide_default_column_types' => '<%= AnnotateModels::NO_DEFAULT_COL_TYPES.join(",") %>', + 'skip_on_db_migrate' => 'false', + 'format_bare' => 'true', + 'format_rdoc' => 'false', + 'format_markdown' => 'false', + 'sort' => 'false', + 'force' => 'false', + 'frozen' => 'false', + 'classified_sort' => 'true', + 'trace' => 'false', + 'wrapper_open' => nil, + 'wrapper_close' => nil, + 'with_comment' => 'true' ) end diff --git a/spec/annotate/annotate_models_spec.rb b/spec/annotate/annotate_models_spec.rb index d7705c888..782084398 100644 --- a/spec/annotate/annotate_models_spec.rb +++ b/spec/annotate/annotate_models_spec.rb @@ -780,6 +780,69 @@ def mock_column(name, type, options = {}) end end + describe '#files_by_pattern' do + subject { AnnotateModels.files_by_pattern(root_directory, pattern_type, options) } + + context 'when pattern_type=additional_file_patterns' do + let(:pattern_type) { 'additional_file_patterns' } + let(:root_directory) { nil } + + context 'with additional_file_patterns' do + let(:additional_file_patterns) do + [ + '%PLURALIZED_MODEL_NAME%/**/*.rb', + '%PLURALIZED_MODEL_NAME%/*_form' + ] + end + + let(:options) { { additional_file_patterns: additional_file_patterns } } + + it do + expect(subject).to eq(additional_file_patterns) + end + end + + context 'without additional_file_patterns' do + let(:options) { {} } + + it do + expect(subject).to eq([]) + end + end + end + end + + describe '#get_patterns' do + subject { AnnotateModels.get_patterns(options, pattern_type) } + + context 'when pattern_type=additional_file_patterns' do + let(:pattern_type) { 'additional_file_patterns' } + + context 'with additional_file_patterns' do + let(:additional_file_patterns) do + [ + '/%PLURALIZED_MODEL_NAME%/**/*.rb', + '/bar/%PLURALIZED_MODEL_NAME%/*_form' + ] + end + + let(:options) { { additional_file_patterns: additional_file_patterns } } + + it do + expect(subject).to eq(additional_file_patterns) + end + end + + context 'without additional_file_patterns' do + let(:options) { {} } + + it do + expect(subject).to eq([]) + end + end + end + end + describe '#get_schema_info with custom options' do def self.when_called_with(options = {}) expected = options.delete(:returns) @@ -1505,6 +1568,24 @@ class Foo < ActiveRecord::Base expect(filename). to eq 'test/unit/example_model_test.rb' end + it 'should return the additional glob' do + filename_template = '/foo/bar/%MODEL_NAME%/testing.rb' + model_name = 'example_model' + table_name = 'example_models' + + filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name) + expect(filename). to eq '/foo/bar/example_model/testing.rb' + end + + it 'should return the additional glob' do + filename_template = '/foo/bar/%PLURALIZED_MODEL_NAME%/testing.rb' + model_name = 'example_model' + table_name = 'example_models' + + filename = AnnotateModels.resolve_filename(filename_template, model_name, table_name) + expect(filename). to eq '/foo/bar/example_models/testing.rb' + end + it 'should return the fixture path for a model' do filename_template = 'test/fixtures/%TABLE_NAME%.yml' model_name = 'example_model' @@ -1523,6 +1604,7 @@ class Foo < ActiveRecord::Base expect(filename). to eq 'test/fixtures/parent/children.yml' end end + describe 'annotating a file' do before do @model_dir = Dir.mktmpdir('annotate_models') From 678d12f97f7e2399d5dba688688447fe0f863621 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Tue, 16 Jul 2019 02:22:28 +0200 Subject: [PATCH 10/27] README: Drop Gemnasium badge, service gone (#638) --- README.rdoc | 1 - 1 file changed, 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index 3e3111fb1..0e3c03deb 100644 --- a/README.rdoc +++ b/README.rdoc @@ -6,7 +6,6 @@ {}[https://coveralls.io/r/ctran/annotate_models?branch=develop] {}[https://codeclimate.com/github/ctran/annotate_models] {Inline docs}[http://inch-ci.org/github/ctran/annotate_models] -{}[https://gemnasium.com/ctran/annotate_models] Add a comment summarizing the current schema to the top or bottom of each of your... From 574cc61bfd9171680b987348298bf7d5b7d4afa5 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Tue, 16 Jul 2019 06:48:13 +0200 Subject: [PATCH 11/27] Gemspec: drop rubyforge_project, it is EOL (#639) The RubyGems gemspec property `rubyforge_project` has been removed without a replacement. Refer to https://github.com/rubygems/rubygems/pull/2436 --- annotate.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/annotate.gemspec b/annotate.gemspec index 2cdeed8c9..c2bf3abbc 100644 --- a/annotate.gemspec +++ b/annotate.gemspec @@ -38,7 +38,6 @@ Gem::Specification.new do |s| s.homepage = 'http://github.com/ctran/annotate_models' s.licenses = ['Ruby'] s.require_paths = ['lib'] - s.rubyforge_project = 'annotate' s.rubygems_version = '2.1.11' s.summary = 'Annotates Rails Models, routes, fixtures, and others based on the database schema.' From f8f1b1787bd812c0fd2a140b3f8eff99574cb608 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Tue, 16 Jul 2019 11:24:55 -0700 Subject: [PATCH 12/27] Refactor Parser (#641) Refactored Parser to isolate changes being made to ENV. This way we have an intermediate step where we know the environment variables being set. --- lib/annotate/parser.rb | 319 ++++++++++++++++++----------------- spec/annotate/parser_spec.rb | 4 +- 2 files changed, 168 insertions(+), 155 deletions(-) diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb index 2b391ff66..d728de267 100644 --- a/lib/annotate/parser.rb +++ b/lib/annotate/parser.rb @@ -3,220 +3,233 @@ module Annotate # Class for handling command line arguments class Parser # rubocop:disable Metrics/ClassLength - def self.parse(args) - new(args).parse + def self.parse(args, env = {}) + new(args, env).parse end - attr_reader :args + attr_reader :args, :options, :env ANNOTATION_POSITIONS = %w[before top after bottom].freeze FILE_TYPE_POSITIONS = %w[position_in_class position_in_factory position_in_fixture position_in_test position_in_routes position_in_serializer].freeze EXCLUSION_LIST = %w[tests fixtures factories serializers].freeze FORMAT_TYPES = %w[bare rdoc markdown].freeze - def initialize(args) + def initialize(args, env) @args = args + @options = default_options + @env = env end def parse - options = default_options + # To split up because right now this method parses and commits + parser.parse!(args) - parser(options).parse!(args) + commit options end private - def parser(options) # rubocop:disable Metrics/MethodLength + def commit + env.each_pair do |key, value| + ENV[key] = value + end + end + + def parser + OptionParser.new do |option_parser| + add_options_to_parser(option_parser) + end + end + + def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength has_set_position = {} positions = ANNOTATION_POSITIONS - OptionParser.new do |opts| - opts.banner = 'Usage: annotate [options] [model_file]*' + option_parser.banner = 'Usage: annotate [options] [model_file]*' - opts.on('-d', '--delete', 'Remove annotations from all model files or the routes.rb file') do - options[:target_action] = :remove_annotations - end + option_parser.on('-d', '--delete', 'Remove annotations from all model files or the routes.rb file') do + @options[:target_action] = :remove_annotations + end - opts.on('-p', '--position [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |p| - ENV['position'] = p + option_parser.on('-p', '--position [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |p| + env['position'] = p - FILE_TYPE_POSITIONS.each do |key| - ENV[key] = p unless has_set_position[key] - end + FILE_TYPE_POSITIONS.each do |key| + env[key] = p unless has_set_position[key] end + end - opts.on('--pc', '--position-in-class [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the model file') do |p| - ENV['position_in_class'] = p - has_set_position['position_in_class'] = true - end + option_parser.on('--pc', '--position-in-class [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the model file') do |p| + env['position_in_class'] = p + has_set_position['position_in_class'] = true + end - opts.on('--pf', '--position-in-factory [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of any factory files') do |p| - ENV['position_in_factory'] = p - has_set_position['position_in_factory'] = true - end + option_parser.on('--pf', '--position-in-factory [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of any factory files') do |p| + env['position_in_factory'] = p + has_set_position['position_in_factory'] = true + end - opts.on('--px', '--position-in-fixture [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of any fixture files') do |p| - ENV['position_in_fixture'] = p - has_set_position['position_in_fixture'] = true - end + option_parser.on('--px', '--position-in-fixture [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of any fixture files') do |p| + env['position_in_fixture'] = p + has_set_position['position_in_fixture'] = true + end - opts.on('--pt', '--position-in-test [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of any test files') do |p| - ENV['position_in_test'] = p - has_set_position['position_in_test'] = true - end + option_parser.on('--pt', '--position-in-test [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of any test files') do |p| + env['position_in_test'] = p + has_set_position['position_in_test'] = true + end - opts.on('--pr', '--position-in-routes [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the routes.rb file') do |p| - ENV['position_in_routes'] = p - has_set_position['position_in_routes'] = true - end + option_parser.on('--pr', '--position-in-routes [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the routes.rb file') do |p| + env['position_in_routes'] = p + has_set_position['position_in_routes'] = true + end - opts.on('--ps', '--position-in-serializer [before|top|after|bottom]', positions, - 'Place the annotations at the top (before) or the bottom (after) of the serializer files') do |p| - ENV['position_in_serializer'] = p - has_set_position['position_in_serializer'] = true - end + option_parser.on('--ps', '--position-in-serializer [before|top|after|bottom]', positions, + 'Place the annotations at the top (before) or the bottom (after) of the serializer files') do |p| + env['position_in_serializer'] = p + has_set_position['position_in_serializer'] = true + end - opts.on('--w', '--wrapper STR', 'Wrap annotation with the text passed as parameter.', - 'If --w option is used, the same text will be used as opening and closing') do |p| - ENV['wrapper'] = p - end + option_parser.on('--w', '--wrapper STR', 'Wrap annotation with the text passed as parameter.', + 'If --w option is used, the same text will be used as opening and closing') do |p| + env['wrapper'] = p + end - opts.on('--wo', '--wrapper-open STR', 'Annotation wrapper opening.') do |p| - ENV['wrapper_open'] = p - end + option_parser.on('--wo', '--wrapper-open STR', 'Annotation wrapper opening.') do |p| + env['wrapper_open'] = p + end - opts.on('--wc', '--wrapper-close STR', 'Annotation wrapper closing') do |p| - ENV['wrapper_close'] = p - end + option_parser.on('--wc', '--wrapper-close STR', 'Annotation wrapper closing') do |p| + env['wrapper_close'] = p + end - opts.on('-r', '--routes', "Annotate routes.rb with the output of 'rake routes'") do - ENV['routes'] = 'true' - end + option_parser.on('-r', '--routes', "Annotate routes.rb with the output of 'rake routes'") do + env['routes'] = 'true' + end - opts.on('-a', '--active-admin', 'Annotate active_admin models') do - ENV['active_admin'] = 'true' - end + option_parser.on('-a', '--active-admin', 'Annotate active_admin models') do + env['active_admin'] = 'true' + end - opts.on('-v', '--version', 'Show the current version of this gem') do - puts "annotate v#{Annotate.version}" - options[:exit] = true - end + option_parser.on('-v', '--version', 'Show the current version of this gem') do + puts "annotate v#{Annotate.version}" + @options[:exit] = true + end - opts.on('-m', '--show-migration', 'Include the migration version number in the annotation') do - ENV['include_version'] = 'yes' - end + option_parser.on('-m', '--show-migration', 'Include the migration version number in the annotation') do + env['include_version'] = 'yes' + end - opts.on('-k', '--show-foreign-keys', - "List the table's foreign key constraints in the annotation") do - ENV['show_foreign_keys'] = 'yes' - end + option_parser.on('-k', '--show-foreign-keys', + "List the table's foreign key constraints in the annotation") do + env['show_foreign_keys'] = 'yes' + end - opts.on('--ck', - '--complete-foreign-keys', 'Complete foreign key names in the annotation') do - ENV['show_foreign_keys'] = 'yes' - ENV['show_complete_foreign_keys'] = 'yes' - end + option_parser.on('--ck', + '--complete-foreign-keys', 'Complete foreign key names in the annotation') do + env['show_foreign_keys'] = 'yes' + env['show_complete_foreign_keys'] = 'yes' + end - opts.on('-i', '--show-indexes', - "List the table's database indexes in the annotation") do - ENV['show_indexes'] = 'yes' - end + option_parser.on('-i', '--show-indexes', + "List the table's database indexes in the annotation") do + env['show_indexes'] = 'yes' + end - opts.on('-s', '--simple-indexes', - "Concat the column's related indexes in the annotation") do - ENV['simple_indexes'] = 'yes' - end + option_parser.on('-s', '--simple-indexes', + "Concat the column's related indexes in the annotation") do + env['simple_indexes'] = 'yes' + end - opts.on('--model-dir dir', - "Annotate model files stored in dir rather than app/models, separate multiple dirs with commas") do |dir| - ENV['model_dir'] = dir - end + option_parser.on('--model-dir dir', + "Annotate model files stored in dir rather than app/models, separate multiple dirs with commas") do |dir| + env['model_dir'] = dir + end - opts.on('--root-dir dir', - "Annotate files stored within root dir projects, separate multiple dirs with commas") do |dir| - ENV['root_dir'] = dir - end + option_parser.on('--root-dir dir', + "Annotate files stored within root dir projects, separate multiple dirs with commas") do |dir| + env['root_dir'] = dir + end - opts.on('--ignore-model-subdirects', - "Ignore subdirectories of the models directory") do |_dir| - ENV['ignore_model_sub_dir'] = 'yes' - end + option_parser.on('--ignore-model-subdirects', + "Ignore subdirectories of the models directory") do |_dir| + env['ignore_model_sub_dir'] = 'yes' + end - opts.on('--sort', - "Sort columns alphabetically, rather than in creation order") do |_dir| - ENV['sort'] = 'yes' - end + option_parser.on('--sort', + "Sort columns alphabetically, rather than in creation order") do |_dir| + env['sort'] = 'yes' + end - opts.on('--classified-sort', - "Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns") do |_dir| - ENV['classified_sort'] = 'yes' - end + option_parser.on('--classified-sort', + "Sort columns alphabetically, but first goes id, then the rest columns, then the timestamp columns and then the association columns") do |_dir| + env['classified_sort'] = 'yes' + end - opts.on('-R', '--require path', - "Additional file to require before loading models, may be used multiple times") do |path| - ENV['require'] = if !ENV['require'].blank? - ENV['require'] + ",#{path}" - else - path - end - end + option_parser.on('-R', '--require path', + "Additional file to require before loading models, may be used multiple times") do |path| + env['require'] = if !env['require'].blank? + env['require'] + ",#{path}" + else + path + end + end - opts.on('-e', '--exclude [tests,fixtures,factories,serializers]', Array, "Do not annotate fixtures, test files, factories, and/or serializers") do |exclusions| - exclusions ||= EXCLUSION_LIST - exclusions.each { |exclusion| ENV["exclude_#{exclusion}"] = 'yes' } - end + option_parser.on('-e', '--exclude [tests,fixtures,factories,serializers]', Array, "Do not annotate fixtures, test files, factories, and/or serializers") do |exclusions| + exclusions ||= EXCLUSION_LIST + exclusions.each { |exclusion| env["exclude_#{exclusion}"] = 'yes' } + end - opts.on('-f', '--format [bare|rdoc|markdown]', FORMAT_TYPES, 'Render Schema Infomation as plain/RDoc/Markdown') do |fmt| - ENV["format_#{fmt}"] = 'yes' - end + option_parser.on('-f', '--format [bare|rdoc|markdown]', FORMAT_TYPES, 'Render Schema Infomation as plain/RDoc/Markdown') do |fmt| + env["format_#{fmt}"] = 'yes' + end - opts.on('--force', 'Force new annotations even if there are no changes.') do |_force| - ENV['force'] = 'yes' - end + option_parser.on('--force', 'Force new annotations even if there are no changes.') do |_force| + env['force'] = 'yes' + end - opts.on('--frozen', 'Do not allow to change annotations. Exits non-zero if there are going to be changes to files.') do - ENV['frozen'] = 'yes' - end + option_parser.on('--frozen', 'Do not allow to change annotations. Exits non-zero if there are going to be changes to files.') do + env['frozen'] = 'yes' + end - opts.on('--timestamp', 'Include timestamp in (routes) annotation') do - ENV['timestamp'] = 'true' - end + option_parser.on('--timestamp', 'Include timestamp in (routes) annotation') do + env['timestamp'] = 'true' + end - opts.on('--trace', 'If unable to annotate a file, print the full stack trace, not just the exception message.') do |_value| - ENV['trace'] = 'yes' - end + option_parser.on('--trace', 'If unable to annotate a file, print the full stack trace, not just the exception message.') do |_value| + env['trace'] = 'yes' + end - opts.on('-I', '--ignore-columns REGEX', "don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`") do |regex| - ENV['ignore_columns'] = regex - end + option_parser.on('-I', '--ignore-columns REGEX', "don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'`") do |regex| + env['ignore_columns'] = regex + end - opts.on('--ignore-routes REGEX', "don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'`") do |regex| - ENV['ignore_routes'] = regex - end + option_parser.on('--ignore-routes REGEX', "don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'`") do |regex| + env['ignore_routes'] = regex + end - opts.on('--hide-limit-column-types VALUES', "don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values| - ENV['hide_limit_column_types'] = values.to_s - end + option_parser.on('--hide-limit-column-types VALUES', "don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values| + env['hide_limit_column_types'] = values.to_s + end - opts.on('--hide-default-column-types VALUES', "don't show default for given column types, separated by commas (i.e., `json,jsonb,hstore`)") do |values| - ENV['hide_default_column_types'] = values.to_s - end + option_parser.on('--hide-default-column-types VALUES', "don't show default for given column types, separated by commas (i.e., `json,jsonb,hstore`)") do |values| + env['hide_default_column_types'] = values.to_s + end - opts.on('--ignore-unknown-models', "don't display warnings for bad model files") do |_values| - ENV['ignore_unknown_models'] = 'true' - end + option_parser.on('--ignore-unknown-models', "don't display warnings for bad model files") do |_values| + env['ignore_unknown_models'] = 'true' + end - opts.on('--with-comment', "include database comments in model annotations") do |_values| - ENV['with_comment'] = 'true' - end + option_parser.on('--with-comment', "include database comments in model annotations") do |_values| + env['with_comment'] = 'true' end end diff --git a/spec/annotate/parser_spec.rb b/spec/annotate/parser_spec.rb index 7ece2903a..467729920 100644 --- a/spec/annotate/parser_spec.rb +++ b/spec/annotate/parser_spec.rb @@ -345,9 +345,9 @@ module Annotate # rubocop:disable Metrics/ModuleLength context "when ENV['require'] is already set" do let(:preset_require_value) { 'some_dir/' } it "appends the path to ENV['require']" do - allow(ENV).to receive(:[]).and_return(preset_require_value) + env = { 'require' => preset_require_value } expect(ENV).to receive(:[]=).with(env_key, "#{preset_require_value},#{set_value}") - Parser.parse([option, set_value]) + Parser.parse([option, set_value], env) end end end From 2e076ee56fc8d5cb171944842903ca38b59192f7 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 6 Aug 2019 19:04:18 +0200 Subject: [PATCH 13/27] Additional file patterns cli (#636) Adds option for additional file patterns (implemented in #633) in the CLI. --- README.rdoc | 2 +- lib/annotate/parser.rb | 8 ++++++++ lib/tasks/annotate_models.rake | 1 + spec/annotate/parser_spec.rb | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index 0e3c03deb..13c0d245d 100644 --- a/README.rdoc +++ b/README.rdoc @@ -163,6 +163,7 @@ you can do so with a simple environment variable, instead of editing the == Options Usage: annotate [options] [model_file]* + --additional_file_patterns Additional file paths or globs to annotate -d, --delete Remove annotations from all model files or the routes.rb file -p [before|top|after|bottom], Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s) --position @@ -215,7 +216,6 @@ you can do so with a simple environment variable, instead of editing the --with-comment include database comments in model annotations - == Sorting By default, columns will be sorted in database order (i.e. the order in which diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb index d728de267..83554365b 100644 --- a/lib/annotate/parser.rb +++ b/lib/annotate/parser.rb @@ -49,10 +49,18 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength option_parser.banner = 'Usage: annotate [options] [model_file]*' + option_parser.on('--additional_file_patterns path1,path2,path3', Array, "Additional file paths or globs to annotate") do |additional_file_patterns| + ENV['additional_file_patterns'] = additional_file_patterns + end + option_parser.on('-d', '--delete', 'Remove annotations from all model files or the routes.rb file') do @options[:target_action] = :remove_annotations end + option_parser.on('--additional_file_patterns path1,path2,path3', Array, "Additional file paths or globs to annotate") do |additional_file_patterns| + ENV['additional_file_patterns'] = additional_file_patterns + end + option_parser.on('-p', '--position [before|top|after|bottom]', positions, 'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |p| env['position'] = p diff --git a/lib/tasks/annotate_models.rake b/lib/tasks/annotate_models.rake index 1d4ab21bc..2e0e38593 100644 --- a/lib/tasks/annotate_models.rake +++ b/lib/tasks/annotate_models.rake @@ -12,6 +12,7 @@ task annotate_models: :environment do options = {is_rake: true} ENV['position'] = options[:position] = Annotate.fallback(ENV['position'], 'before') + options[:additional_file_patterns] = ENV['additional_file_patterns'] ? ENV['additional_file_patterns'].split(',') : [] options[:position_in_class] = Annotate.fallback(ENV['position_in_class'], ENV['position']) options[:position_in_fixture] = Annotate.fallback(ENV['position_in_fixture'], ENV['position']) options[:position_in_factory] = Annotate.fallback(ENV['position_in_factory'], ENV['position']) diff --git a/spec/annotate/parser_spec.rb b/spec/annotate/parser_spec.rb index 467729920..ec8145181 100644 --- a/spec/annotate/parser_spec.rb +++ b/spec/annotate/parser_spec.rb @@ -14,6 +14,21 @@ module Annotate # rubocop:disable Metrics/ModuleLength end end + %w[--additional_file_patterns].each do |option| + describe option do + it 'sets array of paths to :additional_file_patterns' do + # options = "-a ${('foo/bar' 'baz')}" + # Parser.parse(options) + # expect(ENV['additional_file_patterns']).to eq(['foo/bar', 'baz']) + + paths = 'foo/bar,baz' + allow(ENV).to receive(:[]=) + Parser.parse([option, paths]) + expect(ENV).to have_received(:[]=).with('additional_file_patterns', ['foo/bar', 'baz']) + end + end + end + %w[-d --delete].each do |option| describe option do it 'sets target_action to :remove_annotations' do From a906081be466cfd45e82400966c76edb654331b2 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 8 Aug 2019 08:44:14 +0200 Subject: [PATCH 14/27] Additional file patterns docs (#637) Add better documentation for new option for additional file patterns. Implemented in #633 and #636. --- README.rdoc | 30 +++++++++++++++++++++++++----- lib/annotate/parser.rb | 2 +- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/README.rdoc b/README.rdoc index 13c0d245d..7f26112eb 100644 --- a/README.rdoc +++ b/README.rdoc @@ -163,7 +163,7 @@ you can do so with a simple environment variable, instead of editing the == Options Usage: annotate [options] [model_file]* - --additional_file_patterns Additional file paths or globs to annotate + --additional_file_patterns Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`) -d, --delete Remove annotations from all model files or the routes.rb file -p [before|top|after|bottom], Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s) --position @@ -206,15 +206,35 @@ you can do so with a simple environment variable, instead of editing the --frozen Do not allow to change annotations. Exits non-zero if there are going to be changes to files. --timestamp Include timestamp in (routes) annotation --trace If unable to annotate a file, print the full stack trace, not just the exception message. - -I, --ignore-columns REGEX don't annotate columns that match a given REGEX (i.e., `annotate -I '^(id|updated_at|created_at)'` - --ignore-routes REGEX don't annotate routes that match a given REGEX (i.e., `annotate -I '(mobile|resque|pghero)'` + -I, --ignore-columns REGEX don't annotate columns that match a given REGEX (e.g. `annotate -I '^(id|updated_at|created_at)'`) + --ignore-routes REGEX don't annotate routes that match a given REGEX (e.g. `annotate -I '(mobile|resque|pghero)'`)_ --hide-limit-column-types VALUES - don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`) + don't show limit for given column types, separated by commas (e.g. `integer,boolean,text`) --hide-default-column-types VALUES - don't show default for given column types, separated by commas (i.e., `json,jsonb,hstore`) + don't show default for given column types, separated by commas (e.g. `json,jsonb,hstore`) --ignore-unknown-models don't display warnings for bad model files --with-comment include database comments in model annotations +=== Option: +additional_file_patterns+ + +CLI: +--additional_file_patterns+
+Ruby: +:additional_file_patterns+ + +Provide additional paths for the gem to annotate. These paths can include globs. +It is recommended to use absolute paths. Here are some examples: + + +- /app/lib/decorates/%MODEL_NAME%/*.rb +- /app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb +- /app/lib/forms/%TABLE_NAME%/*.rb + +The appropriate model will be inferred using the %*% syntax, annotating any matching files. +It works with existing filename resolutions (options for which can be found in the +resolve_filename+ method of ++annotate_models.rb+). + +When using in a Rails config, you can use the following: + +File.join(Rails.application.root, 'app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb') == Sorting diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb index 83554365b..50de99d6b 100644 --- a/lib/annotate/parser.rb +++ b/lib/annotate/parser.rb @@ -49,7 +49,7 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength option_parser.banner = 'Usage: annotate [options] [model_file]*' - option_parser.on('--additional_file_patterns path1,path2,path3', Array, "Additional file paths or globs to annotate") do |additional_file_patterns| + option_parser.on('--additional_file_patterns path1,path2,path3', Array, "Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`)") do |additional_file_patterns| ENV['additional_file_patterns'] = additional_file_patterns end From 0917c075fdad1e5e988d3e93950bdf5593758ee7 Mon Sep 17 00:00:00 2001 From: Prateek Choudhary Date: Tue, 3 Sep 2019 03:09:48 +0530 Subject: [PATCH 15/27] Fix spelling mistake in annotate_routes file doc (#645) --- lib/annotate/annotate_routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/annotate/annotate_routes.rb b/lib/annotate/annotate_routes.rb index 4ad9f9136..c98910987 100644 --- a/lib/annotate/annotate_routes.rb +++ b/lib/annotate/annotate_routes.rb @@ -10,7 +10,7 @@ # Yes, it's simple but I'm thick and often need a reminder of what my routes # mean. # -# Running this task will replace any exising route comment generated by the +# Running this task will replace any existing route comment generated by the # task. Best to back up your routes file before running: # # Author: From 2775001d7e6ad804bf3797b8790207fd7598d109 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Mon, 2 Sep 2019 16:33:21 -0700 Subject: [PATCH 16/27] Tidy spec directory (#646) In looking into #563, I realized there are gaps in test coverage. For example, `bin/annotate` doesn't have any tests. Tidying the spec directory to make it easier to add tests in future work. --- .rubocop_todo.yml | 83 ++++++------------- .../annotate/annotate_models_spec.rb | 4 +- .../annotate/annotate_routes_spec.rb | 2 +- spec/{ => lib}/annotate/parser_spec.rb | 2 +- spec/{ => lib}/annotate_spec.rb | 2 +- .../tasks/annotate_models_migrate_spec.rb | 2 +- 6 files changed, 33 insertions(+), 62 deletions(-) rename spec/{ => lib}/annotate/annotate_models_spec.rb (99%) rename spec/{ => lib}/annotate/annotate_routes_spec.rb (99%) rename spec/{ => lib}/annotate/parser_spec.rb (99%) rename spec/{ => lib}/annotate_spec.rb (70%) rename spec/{ => lib}/tasks/annotate_models_migrate_spec.rb (98%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 552b76072..aa519ba7f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2019-06-16 12:01:03 -0700 using RuboCop version 0.68.1. +# on 2019-09-02 16:23:56 -0700 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 @@ -49,9 +49,9 @@ Gemspec/RequiredRubyVersion: # Cop supports --auto-correct. Layout/AlignArray: Exclude: - - 'spec/annotate/annotate_models_spec.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' -# Offense count: 104 +# Offense count: 107 # Cop supports --auto-correct. # Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table @@ -60,11 +60,11 @@ Layout/AlignArray: Layout/AlignHash: Exclude: - 'lib/generators/annotate/templates/auto_annotate_models.rake' - - 'spec/annotate/annotate_models_spec.rb' - 'spec/integration/rails_2.3_with_bundler/config/initializers/unified_initializer.rb' - 'spec/integration/rails_4.1.1/lib/tasks/auto_annotate_models.rake' - 'spec/integration/rails_4.2.0/lib/tasks/auto_annotate_models.rake' - 'spec/integration/standalone/config/init.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -78,7 +78,6 @@ Layout/BlockAlignment: # Cop supports --auto-correct. Layout/ClosingHeredocIndentation: Exclude: - - 'spec/annotate/annotate_models_spec.rb' - 'spec/integration/rails_2.3_with_bundler.rb' - 'spec/integration/rails_3.2.2.rb' - 'spec/integration/rails_3.2.8.rb' @@ -86,8 +85,9 @@ Layout/ClosingHeredocIndentation: - 'spec/integration/rails_3.2_custom_inflections.rb' - 'spec/integration/rails_3.2_with_asset_pipeline.rb' - 'spec/integration/standalone.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' -# Offense count: 14 +# Offense count: 13 # Cop supports --auto-correct. Layout/EmptyLineAfterGuardClause: Exclude: @@ -102,7 +102,6 @@ Layout/EmptyLineAfterGuardClause: Layout/EmptyLineAfterMagicComment: Exclude: - 'annotate.gemspec' - - 'spec/annotate/annotate_models_spec.rb' - 'spec/integration/rails_3.2.2/db/schema.rb' - 'spec/integration/rails_3.2.8/db/schema.rb' - 'spec/integration/rails_3.2_autoloading_factory_girl/db/schema.rb' @@ -111,6 +110,7 @@ Layout/EmptyLineAfterMagicComment: - 'spec/integration/rails_4.1.1/db/schema.rb' - 'spec/integration/rails_4.2.0/db/schema.rb' - 'spec/integration/standalone/db/schema.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 2 # Cop supports --auto-correct. @@ -129,7 +129,7 @@ Layout/EmptyLinesAroundAccessModifier: # Cop supports --auto-correct. Layout/EmptyLinesAroundArguments: Exclude: - - 'spec/annotate/annotate_routes_spec.rb' + - 'spec/lib/annotate/annotate_routes_spec.rb' # Offense count: 6 # Cop supports --auto-correct. @@ -179,7 +179,6 @@ Layout/IndentFirstHashElement: # SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent Layout/IndentHeredoc: Exclude: - - 'spec/annotate/annotate_models_spec.rb' - 'spec/integration/integration_spec.rb' - 'spec/integration/rails_2.3_with_bundler.rb' - 'spec/integration/rails_3.2.2.rb' @@ -188,6 +187,7 @@ Layout/IndentHeredoc: - 'spec/integration/rails_3.2_custom_inflections.rb' - 'spec/integration/rails_3.2_with_asset_pipeline.rb' - 'spec/integration/standalone.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -214,7 +214,7 @@ Layout/IndentationWidth: # SupportedStyles: aligned, indented, indented_relative_to_receiver Layout/MultilineMethodCallIndentation: Exclude: - - 'spec/annotate/annotate_routes_spec.rb' + - 'spec/lib/annotate/annotate_routes_spec.rb' # Offense count: 5 # Cop supports --auto-correct. @@ -339,8 +339,8 @@ Layout/TrailingBlankLines: # Configuration parameters: AllowInHeredoc. Layout/TrailingWhitespace: Exclude: - - 'spec/annotate/annotate_routes_spec.rb' - 'spec/integration/rails_2.3_with_bundler/db/schema.rb' + - 'spec/lib/annotate/annotate_routes_spec.rb' # Offense count: 3 # Configuration parameters: AllowSafeAssignment. @@ -349,12 +349,6 @@ Lint/AssignmentInCondition: - 'lib/annotate/annotate_models.rb' - 'spec/integration/rails_2.3_with_bundler/config/boot.rb' -# Offense count: 2 -# Cop supports --auto-correct. -Lint/BigDecimalNew: - Exclude: - - 'spec/annotate/annotate_models_spec.rb' - # Offense count: 6 # Cop supports --auto-correct. Lint/DeprecatedClassMethods: @@ -412,18 +406,11 @@ Lint/ShadowingOuterLocalVariable: Exclude: - 'Rakefile' -# Offense count: 7 -# Cop supports --auto-correct. -# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. -Lint/UnusedBlockArgument: - Exclude: - - 'bin/annotate' - -# Offense count: 19 +# Offense count: 20 Metrics/AbcSize: Max: 138 -# Offense count: 27 +# Offense count: 28 # Configuration parameters: CountComments, ExcludedMethods. # ExcludedMethods: refine Metrics/BlockLength: @@ -438,7 +425,7 @@ Metrics/BlockNesting: Metrics/CyclomaticComplexity: Max: 36 -# Offense count: 29 +# Offense count: 30 # Configuration parameters: CountComments, ExcludedMethods. Metrics/MethodLength: Max: 75 @@ -457,8 +444,8 @@ Naming/AccessorMethodName: # Blacklist: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) Naming/HeredocDelimiterNaming: Exclude: - - 'spec/annotate/annotate_models_spec.rb' - - 'spec/annotate/annotate_routes_spec.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' + - 'spec/lib/annotate/annotate_routes_spec.rb' # Offense count: 2 # Configuration parameters: EnforcedStyleForLeadingUnderscores. @@ -531,14 +518,6 @@ Style/ClassVars: Exclude: - 'lib/tasks/annotate_models_migrate.rake' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions. -# SupportedStyles: assign_to_condition, assign_inside_condition -Style/ConditionalAssignment: - Exclude: - - 'bin/annotate' - # Offense count: 1 # Cop supports --auto-correct. Style/Dir: @@ -562,7 +541,6 @@ Style/Documentation: Style/Encoding: Exclude: - 'annotate.gemspec' - - 'spec/annotate/annotate_models_spec.rb' - 'spec/integration/rails_3.2.2/db/schema.rb' - 'spec/integration/rails_3.2.8/db/schema.rb' - 'spec/integration/rails_3.2_autoloading_factory_girl/db/schema.rb' @@ -571,6 +549,7 @@ Style/Encoding: - 'spec/integration/rails_4.1.1/db/schema.rb' - 'spec/integration/rails_4.2.0/db/schema.rb' - 'spec/integration/standalone/db/schema.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 48 # Cop supports --auto-correct. @@ -593,7 +572,7 @@ Style/FormatStringToken: Exclude: - 'lib/annotate/annotate_models.rb' -# Offense count: 184 +# Offense count: 186 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: when_needed, always, never @@ -690,17 +669,15 @@ Style/NumericPredicate: - 'lib/annotate.rb' - 'lib/annotate/annotate_models.rb' -# Offense count: 24 +# Offense count: 20 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - 'annotate.gemspec' - - 'bin/annotate' - 'lib/annotate/annotate_models.rb' - 'lib/annotate/annotate_routes.rb' - 'lib/tasks/annotate_models_migrate.rake' - - 'spec/annotate/annotate_models_spec.rb' - 'spec/integration/rails_3.2.2/config/application.rb' - 'spec/integration/rails_3.2.8/config/application.rb' - 'spec/integration/rails_3.2_autoloading_factory_girl/config/application.rb' @@ -708,8 +685,9 @@ Style/PercentLiteralDelimiters: - 'spec/integration/rails_3.2_with_asset_pipeline/config/application.rb' - 'spec/integration/rails_4.1.1/app/models/task.rb' - 'spec/integration/rails_4.2.0/app/models/task.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' + - 'spec/lib/tasks/annotate_models_migrate_spec.rb' - 'spec/spec_helper.rb' - - 'spec/tasks/annotate_models_migrate_spec.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -730,7 +708,7 @@ Style/RaiseArgs: Style/RedundantBegin: Exclude: - 'lib/annotate/annotate_models.rb' - - 'spec/annotate/annotate_models_spec.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -784,12 +762,11 @@ Style/SafeNavigation: Exclude: - 'lib/annotate/annotate_models.rb' -# Offense count: 2 +# Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowAsExpressionSeparator. Style/Semicolon: Exclude: - - 'bin/annotate' - 'spec/integration/rails_2.3_with_bundler/config/initializers/unified_initializer.rb' # Offense count: 18 @@ -801,7 +778,7 @@ Style/StderrPuts: - 'lib/annotate/annotate_models.rb' - 'spec/integration/rails_2.3_with_bundler/config/boot.rb' -# Offense count: 243 +# Offense count: 247 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -827,7 +804,7 @@ Style/SymbolArray: # Cop supports --auto-correct. Style/SymbolLiteral: Exclude: - - 'spec/annotate/annotate_models_spec.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -835,7 +812,7 @@ Style/SymbolLiteral: # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArrayLiteral: Exclude: - - 'spec/annotate/annotate_models_spec.rb' + - 'spec/lib/annotate/annotate_models_spec.rb' # Offense count: 2 # Cop supports --auto-correct. @@ -846,12 +823,6 @@ Style/TrailingCommaInHashLiteral: - 'spec/integration/rails_4.1.1/lib/tasks/auto_annotate_models.rake' - 'spec/integration/rails_4.2.0/lib/tasks/auto_annotate_models.rake' -# Offense count: 2 -# Cop supports --auto-correct. -Style/UnneededInterpolation: - Exclude: - - 'bin/annotate' - # Offense count: 4 # Cop supports --auto-correct. Style/UnneededPercentQ: @@ -859,7 +830,7 @@ Style/UnneededPercentQ: - 'annotate.gemspec' - 'spec/integration/rails_2.3_with_bundler/config/boot.rb' -# Offense count: 431 +# Offense count: 465 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https diff --git a/spec/annotate/annotate_models_spec.rb b/spec/lib/annotate/annotate_models_spec.rb similarity index 99% rename from spec/annotate/annotate_models_spec.rb rename to spec/lib/annotate/annotate_models_spec.rb index 782084398..f95a9e290 100644 --- a/spec/annotate/annotate_models_spec.rb +++ b/spec/lib/annotate/annotate_models_spec.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require File.dirname(__FILE__) + '/../spec_helper.rb' +require_relative '../../spec_helper' require 'annotate/annotate_models' require 'annotate/active_record_patch' require 'active_support/core_ext/string' @@ -1819,7 +1819,7 @@ class User < ActiveRecord::Base end expect(error_output).to include("Unable to annotate #{@model_dir}/user.rb: oops") - expect(error_output).to include('/spec/annotate/annotate_models_spec.rb:') + expect(error_output).to include('/spec/lib/annotate/annotate_models_spec.rb:') end end diff --git a/spec/annotate/annotate_routes_spec.rb b/spec/lib/annotate/annotate_routes_spec.rb similarity index 99% rename from spec/annotate/annotate_routes_spec.rb rename to spec/lib/annotate/annotate_routes_spec.rb index 1a34bbee0..2d2cd4eae 100644 --- a/spec/annotate/annotate_routes_spec.rb +++ b/spec/lib/annotate/annotate_routes_spec.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../spec_helper.rb' +require_relative '../../spec_helper' require 'annotate/annotate_routes' describe AnnotateRoutes do diff --git a/spec/annotate/parser_spec.rb b/spec/lib/annotate/parser_spec.rb similarity index 99% rename from spec/annotate/parser_spec.rb rename to spec/lib/annotate/parser_spec.rb index ec8145181..bd680e9c8 100644 --- a/spec/annotate/parser_spec.rb +++ b/spec/lib/annotate/parser_spec.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../spec_helper.rb' +require_relative '../../spec_helper' module Annotate # rubocop:disable Metrics/ModuleLength describe Parser do # rubocop:disable Metrics/BlockLength diff --git a/spec/annotate_spec.rb b/spec/lib/annotate_spec.rb similarity index 70% rename from spec/annotate_spec.rb rename to spec/lib/annotate_spec.rb index 542ac63ba..2912f2084 100644 --- a/spec/annotate_spec.rb +++ b/spec/lib/annotate_spec.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/spec_helper.rb' +require_relative '../spec_helper' describe Annotate do it 'should have a version' do diff --git a/spec/tasks/annotate_models_migrate_spec.rb b/spec/lib/tasks/annotate_models_migrate_spec.rb similarity index 98% rename from spec/tasks/annotate_models_migrate_spec.rb rename to spec/lib/tasks/annotate_models_migrate_spec.rb index 8c30e1c93..7172658a5 100644 --- a/spec/tasks/annotate_models_migrate_spec.rb +++ b/spec/lib/tasks/annotate_models_migrate_spec.rb @@ -1,4 +1,4 @@ -require_relative '../spec_helper' +require_relative '../../spec_helper' describe 'ActiveRecord migration rake task hooks' do before do From 846c7f8e7e05e7c936d6c47dac6dc6413cb382f0 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Mon, 2 Sep 2019 18:00:57 -0700 Subject: [PATCH 17/27] Make it possible to annotate models and routes together (#647) Prior to this change, `Annotate.include_models?` returned the inverse of `Annotate.include_routes?`. This made it so annotating models and routes was not possible to do together. This PR adds an explicit `--models` flag and also adds it the option to `lib/generators/annotate/templates/auto_annotate_models.rake` with the default being set to `false`. Fixes #563 and undoes the bug introduced in #485. --- README.rdoc | 5 +++-- lib/annotate.rb | 4 ++-- lib/annotate/parser.rb | 4 ++++ .../annotate/templates/auto_annotate_models.rake | 1 + spec/lib/annotate/parser_spec.rb | 11 +++++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/README.rdoc b/README.rdoc index 7f26112eb..a5b3c88c4 100644 --- a/README.rdoc +++ b/README.rdoc @@ -89,11 +89,11 @@ To annotate all your models, tests, fixtures, and factories: To annotate just your models, tests, and factories: - annotate --exclude fixtures + annotate --models --exclude fixtures To annotate just your models: - annotate --exclude tests,fixtures,factories,serializers + annotate --models To annotate routes.rb: @@ -184,6 +184,7 @@ you can do so with a simple environment variable, instead of editing the --wo, --wrapper-open STR Annotation wrapper opening. --wc, --wrapper-close STR Annotation wrapper closing -r, --routes Annotate routes.rb with the output of 'rake routes' + --models Annotate ActiveRecord models -a, --active-admin Annotate active_admin models -v, --version Show the current version of this gem -m, --show-migration Include the migration version number in the annotation diff --git a/lib/annotate.rb b/lib/annotate.rb index db223a333..765e6af44 100644 --- a/lib/annotate.rb +++ b/lib/annotate.rb @@ -37,7 +37,7 @@ module Annotate ].freeze OTHER_OPTIONS = [ :additional_file_patterns, :ignore_columns, :skip_on_db_migrate, :wrapper_open, :wrapper_close, - :wrapper, :routes, :hide_limit_column_types, :hide_default_column_types, + :wrapper, :routes, :models, :hide_limit_column_types, :hide_default_column_types, :ignore_routes, :active_admin ].freeze PATH_OPTIONS = [ @@ -115,7 +115,7 @@ def self.include_routes? end def self.include_models? - ENV['routes'] !~ TRUE_RE + ENV['models'] =~ TRUE_RE end def self.loaded_tasks=(val) diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb index 50de99d6b..9ca0197aa 100644 --- a/lib/annotate/parser.rb +++ b/lib/annotate/parser.rb @@ -123,6 +123,10 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength env['routes'] = 'true' end + option_parser.on('--models', "Annotate routes.rb with the output of 'rake routes'") do + env['models'] = 'true' + end + option_parser.on('-a', '--active-admin', 'Annotate active_admin models') do env['active_admin'] = 'true' end diff --git a/lib/generators/annotate/templates/auto_annotate_models.rake b/lib/generators/annotate/templates/auto_annotate_models.rake index 911c44211..473f3ea1f 100644 --- a/lib/generators/annotate/templates/auto_annotate_models.rake +++ b/lib/generators/annotate/templates/auto_annotate_models.rake @@ -9,6 +9,7 @@ if Rails.env.development? Annotate.set_defaults( 'additional_file_patterns' => [], 'routes' => 'false', + 'models' => 'false', 'position_in_routes' => 'before', 'position_in_class' => 'before', 'position_in_test' => 'before', diff --git a/spec/lib/annotate/parser_spec.rb b/spec/lib/annotate/parser_spec.rb index bd680e9c8..797e13c56 100644 --- a/spec/lib/annotate/parser_spec.rb +++ b/spec/lib/annotate/parser_spec.rb @@ -222,6 +222,17 @@ module Annotate # rubocop:disable Metrics/ModuleLength end end + %w[--models].each do |option| + describe option do + let(:env_key) { 'models' } + let(:set_value) { 'true' } + it 'sets the ENV variable' do + expect(ENV).to receive(:[]=).with(env_key, set_value) + Parser.parse([option]) + end + end + end + %w[-a --active-admin].each do |option| describe option do let(:env_key) { 'active_admin' } From 7fe611f8d877d8bc6d0edcb1b693c81cb9266fdf Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Mon, 2 Sep 2019 22:25:19 -0700 Subject: [PATCH 18/27] Update tested ruby versions (#648) Updating tested ruby versions to use latest versions. * Bump ruby 2.4.6 -> 2.4.7 * Bump ruby 2.5.5 -> 2.5.6 * Add ruby 2.6.4 * Remove old versions of 2.6.X --- .travis.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ecc68d6f..1d5ff3f4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,9 @@ language: ruby rvm: - 2.2.10 - 2.3.8 -- 2.4.6 -- 2.5.5 -- 2.6.0 -- 2.6.1 -- 2.6.2 -- 2.6.3 +- 2.4.7 +- 2.5.6 +- 2.6.4 - ruby-head matrix: From b39df314f179b9620abb2a76a17deef4a32fc9fc Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Mon, 2 Sep 2019 22:53:26 -0700 Subject: [PATCH 19/27] Update CHANGELOG --- CHANGELOG.rdoc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 516131d91..d21e18179 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,13 @@ +== 3.0.0 +* Added `--models` CLI option fixing issue #563 (#647) +* Added `--additional_file_patterns` option for additional file patterns (#633) #636) #637) +* Refactored CLI parser (#646) +* Fixed BigDecimal.new deprecation warning (#634) +* Fixed annotations for columns with long data types (#622) +* Made methods private in AnnotateRoutes (#598) + +See https://github.com/ctran/annotate_models/releases/tag/v3.0.0 + == 2.7.5 See https://github.com/ctran/annotate_models/releases/tag/v2.7.5 From 0ad3424ed83b78e6da40dc11c32fde5aeeced22e Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Mon, 2 Sep 2019 22:55:50 -0700 Subject: [PATCH 20/27] v3.0.0 --- lib/annotate/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/annotate/version.rb b/lib/annotate/version.rb index 0e7a17628..918b88d59 100644 --- a/lib/annotate/version.rb +++ b/lib/annotate/version.rb @@ -1,5 +1,5 @@ module Annotate def self.version - '2.7.5' + '3.0.0' end end From 6de3ed8050b64cfc99ad0f3867f5a524265f3286 Mon Sep 17 00:00:00 2001 From: rnitta Date: Tue, 17 Sep 2019 02:18:28 +0900 Subject: [PATCH 21/27] Fix --models option description to match README (#649) --- lib/annotate/parser.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb index 9ca0197aa..f06ec1562 100644 --- a/lib/annotate/parser.rb +++ b/lib/annotate/parser.rb @@ -123,7 +123,7 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength env['routes'] = 'true' end - option_parser.on('--models', "Annotate routes.rb with the output of 'rake routes'") do + option_parser.on('--models', "Annotate ActiveRecord models") do env['models'] = 'true' end From c710caac375372c93bb25ce7d8795422cf06dce9 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Thu, 26 Sep 2019 13:08:42 +0900 Subject: [PATCH 22/27] Refactor and tidy lib/annotate.rb (#653) Adds tests for `.include_routes?`, `.include_models?`, `.skip_on_migration?`. Also moves the `TRUE_RE` under the `Annotate::Constants` namespace. --- lib/annotate.rb | 11 +++++------ lib/annotate/annotate_models.rb | 6 +++--- lib/annotate/constants.rb | 5 +++++ spec/lib/annotate_spec.rb | 27 +++++++++++++++++++++++++-- 4 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 lib/annotate/constants.rb diff --git a/lib/annotate.rb b/lib/annotate.rb index 765e6af44..eab454b40 100644 --- a/lib/annotate.rb +++ b/lib/annotate.rb @@ -4,6 +4,7 @@ require 'annotate/version' require 'annotate/annotate_models' require 'annotate/annotate_routes' +require 'annotate/constants' begin # ActiveSupport 3.x... @@ -16,8 +17,6 @@ end module Annotate - TRUE_RE = /^(true|t|yes|y|1)$/i - ## # The set of available options to customize the behavior of Annotate. # @@ -107,15 +106,15 @@ def self.reset_options end def self.skip_on_migration? - ENV['ANNOTATE_SKIP_ON_DB_MIGRATE'] =~ TRUE_RE || ENV['skip_on_db_migrate'] =~ TRUE_RE + ENV['ANNOTATE_SKIP_ON_DB_MIGRATE'] =~ Constants::TRUE_RE || ENV['skip_on_db_migrate'] =~ Constants::TRUE_RE end def self.include_routes? - ENV['routes'] =~ TRUE_RE + ENV['routes'] =~ Constants::TRUE_RE end def self.include_models? - ENV['models'] =~ TRUE_RE + ENV['models'] =~ Constants::TRUE_RE end def self.loaded_tasks=(val) @@ -199,7 +198,7 @@ def self.fallback(*args) def self.true?(val) return false if val.blank? - return false unless val =~ TRUE_RE + return false unless val =~ Constants::TRUE_RE true end end diff --git a/lib/annotate/annotate_models.rb b/lib/annotate/annotate_models.rb index b2cf7453d..b306d0b84 100644 --- a/lib/annotate/annotate_models.rb +++ b/lib/annotate/annotate_models.rb @@ -2,9 +2,9 @@ require 'bigdecimal' -module AnnotateModels - TRUE_RE = /^(true|t|yes|y|1)$/i +require 'annotate/constants' +module AnnotateModels # Annotate Models plugin use this header COMPAT_PREFIX = '== Schema Info'.freeze COMPAT_PREFIX_MD = '## Schema Info'.freeze @@ -590,7 +590,7 @@ def remove_annotation_of_file(file_name, options = {}) def matched_types(options) types = MATCHED_TYPES.dup - types << 'admin' if options[:active_admin] =~ TRUE_RE && !types.include?('admin') + types << 'admin' if options[:active_admin] =~ Annotate::Constants::TRUE_RE && !types.include?('admin') types << 'additional_file_patterns' if options[:additional_file_patterns].present? types diff --git a/lib/annotate/constants.rb b/lib/annotate/constants.rb new file mode 100644 index 000000000..5c76d8c8c --- /dev/null +++ b/lib/annotate/constants.rb @@ -0,0 +1,5 @@ +module Annotate + module Constants + TRUE_RE = /^(true|t|yes|y|1)$/i.freeze + end +end diff --git a/spec/lib/annotate_spec.rb b/spec/lib/annotate_spec.rb index 2912f2084..3b7c30ce8 100644 --- a/spec/lib/annotate_spec.rb +++ b/spec/lib/annotate_spec.rb @@ -1,7 +1,30 @@ require_relative '../spec_helper' describe Annotate do - it 'should have a version' do - expect(Annotate.version).to be_instance_of(String) + describe '.version' do + it 'has version' do + expect(Annotate.version).to be_instance_of(String) + end + end + + describe '.skip_on_migration?' do + it "checks ENV for 'ANNOTATE_SKIP_ON_DB_MIGRATE' or 'skip_on_db_migrate'" do + expect(ENV).to receive(:[]).twice + described_class.skip_on_migration? + end + end + + describe '.include_routes?' do + it "checks ENV with 'routes'" do + expect(ENV).to receive(:[]).with('routes') + described_class.include_routes? + end + end + + describe '.include_models?' do + it "checks ENV with 'models'" do + expect(ENV).to receive(:[]).with('models') + described_class.include_models? + end end end From 05ee21675f51db657f067ee3b47e8f2918d0303f Mon Sep 17 00:00:00 2001 From: Cuong Tran Date: Thu, 26 Sep 2019 22:50:16 -0700 Subject: [PATCH 23/27] Integrate Github actions for CI (#619) --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ .github/workflows/milestone.yml | 12 ++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/milestone.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..83d7433c1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI +on: [push] +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + ruby: + - 2.3.x + - 2.4.x + - 2.6.x + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup System + run: | + sudo apt-get install libsqlite3-dev + - name: Setup Ruby + uses: actions/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - name: Bundle + run: | + gem update --system + gem update bundler + bundle install --jobs 4 --retry 3 + - name: Test + run: bundle exec rubocop && bundle exec rspec diff --git a/.github/workflows/milestone.yml b/.github/workflows/milestone.yml new file mode 100644 index 000000000..290677f56 --- /dev/null +++ b/.github/workflows/milestone.yml @@ -0,0 +1,12 @@ +on: milestone +name: On Milestone +jobs: + createReleaseNotes: + name: Create Release Notes + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Create Release Notes + uses: mmornati/release-notes-generator-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From cad47f569812ebc3fa9e514b9af983e5e76736c9 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Sat, 28 Sep 2019 12:50:20 +0900 Subject: [PATCH 24/27] Make --additional_file_patterns consistent by using dashes (#654) Changed references to `--additional_file_patterns` to be `--additional-file-patterns` to make it consistent with other flags. --- README.rdoc | 14 +++++++------- lib/annotate/parser.rb | 6 +----- spec/lib/annotate/parser_spec.rb | 6 +----- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/README.rdoc b/README.rdoc index a5b3c88c4..a06014a64 100644 --- a/README.rdoc +++ b/README.rdoc @@ -163,7 +163,7 @@ you can do so with a simple environment variable, instead of editing the == Options Usage: annotate [options] [model_file]* - --additional_file_patterns Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`) + --additional-file-patterns Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`) -d, --delete Remove annotations from all model files or the routes.rb file -p [before|top|after|bottom], Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s) --position @@ -216,18 +216,18 @@ you can do so with a simple environment variable, instead of editing the --ignore-unknown-models don't display warnings for bad model files --with-comment include database comments in model annotations -=== Option: +additional_file_patterns+ +=== Option: +additional-file-patterns+ -CLI: +--additional_file_patterns+
-Ruby: +:additional_file_patterns+ +CLI: +--additional-file-patterns+
+Ruby: +:additional-file-patterns+ Provide additional paths for the gem to annotate. These paths can include globs. It is recommended to use absolute paths. Here are some examples: -- /app/lib/decorates/%MODEL_NAME%/*.rb -- /app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb -- /app/lib/forms/%TABLE_NAME%/*.rb +- /app/lib/decorates/%MODEL_NAME%/*.rb +- /app/lib/forms/%PLURALIZED_MODEL_NAME%/**/*.rb +- /app/lib/forms/%TABLE_NAME%/*.rb The appropriate model will be inferred using the %*% syntax, annotating any matching files. It works with existing filename resolutions (options for which can be found in the +resolve_filename+ method of diff --git a/lib/annotate/parser.rb b/lib/annotate/parser.rb index f06ec1562..97b59551a 100644 --- a/lib/annotate/parser.rb +++ b/lib/annotate/parser.rb @@ -49,7 +49,7 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength option_parser.banner = 'Usage: annotate [options] [model_file]*' - option_parser.on('--additional_file_patterns path1,path2,path3', Array, "Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`)") do |additional_file_patterns| + option_parser.on('--additional-file-patterns path1,path2,path3', Array, "Additional file paths or globs to annotate, separated by commas (e.g. `/foo/bar/%model_name%/*.rb,/baz/%model_name%.rb`)") do |additional_file_patterns| ENV['additional_file_patterns'] = additional_file_patterns end @@ -57,10 +57,6 @@ def add_options_to_parser(option_parser) # rubocop:disable Metrics/MethodLength @options[:target_action] = :remove_annotations end - option_parser.on('--additional_file_patterns path1,path2,path3', Array, "Additional file paths or globs to annotate") do |additional_file_patterns| - ENV['additional_file_patterns'] = additional_file_patterns - end - option_parser.on('-p', '--position [before|top|after|bottom]', positions, 'Place the annotations at the top (before) or the bottom (after) of the model/test/fixture/factory/route/serializer file(s)') do |p| env['position'] = p diff --git a/spec/lib/annotate/parser_spec.rb b/spec/lib/annotate/parser_spec.rb index 797e13c56..7681b3d4a 100644 --- a/spec/lib/annotate/parser_spec.rb +++ b/spec/lib/annotate/parser_spec.rb @@ -14,13 +14,9 @@ module Annotate # rubocop:disable Metrics/ModuleLength end end - %w[--additional_file_patterns].each do |option| + %w[--additional-file-patterns].each do |option| describe option do it 'sets array of paths to :additional_file_patterns' do - # options = "-a ${('foo/bar' 'baz')}" - # Parser.parse(options) - # expect(ENV['additional_file_patterns']).to eq(['foo/bar', 'baz']) - paths = 'foo/bar,baz' allow(ENV).to receive(:[]=) Parser.parse([option, paths]) From 1a805a3ab62685253e6653d59b8ad28faeb4e2c0 Mon Sep 17 00:00:00 2001 From: Martins Polakovs Date: Sun, 29 Sep 2019 16:22:52 +0300 Subject: [PATCH 25/27] Add mising files to gemspec (#660) Currently the gem released as version 3.0.0 is broken. Fixes #657 The gem is missing constants.rb and parser.rb file --- annotate.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/annotate.gemspec b/annotate.gemspec index c2bf3abbc..d0565352c 100644 --- a/annotate.gemspec +++ b/annotate.gemspec @@ -26,6 +26,8 @@ Gem::Specification.new do |s| 'lib/annotate/active_record_patch.rb', 'lib/annotate/annotate_models.rb', 'lib/annotate/annotate_routes.rb', + 'lib/annotate/constants.rb', + 'lib/annotate/parser.rb', 'lib/annotate/tasks.rb', 'lib/annotate/version.rb', 'lib/generators/annotate/USAGE', From d4c35e8be5604ceaf72118889cfdc87c975d35ed Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Sun, 29 Sep 2019 22:44:00 +0900 Subject: [PATCH 26/27] Update CHANGELOG --- CHANGELOG.rdoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index d21e18179..1cca1f405 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,11 @@ +== 3.0.2 +* Fixes `LoadError` due to gemspec not referencing `parser.rb`, issue #657 (#660) +* Changes `--additional_file_patterns` to use dashes `--additional-file-patterns` for consistency (#649) +* Refactor: moving constants into `constants.rb` (#653) + +== 3.0.1 +* Skipped as an official release, used the 3.0.1 patch for setting up Github Actions (#619) + == 3.0.0 * Added `--models` CLI option fixing issue #563 (#647) * Added `--additional_file_patterns` option for additional file patterns (#633) #636) #637) From 767744f27bf3d8575e07126077b4e1c1bf4efea0 Mon Sep 17 00:00:00 2001 From: "Andrew W. Lee" Date: Sun, 29 Sep 2019 22:44:53 +0900 Subject: [PATCH 27/27] v3.0.2 --- lib/annotate/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/annotate/version.rb b/lib/annotate/version.rb index 918b88d59..80c85086d 100644 --- a/lib/annotate/version.rb +++ b/lib/annotate/version.rb @@ -1,5 +1,5 @@ module Annotate def self.version - '3.0.0' + '3.0.2' end end