diff --git a/README.rdoc b/README.rdoc index 5e4582df0..3e3111fb1 100644 --- a/README.rdoc +++ b/README.rdoc @@ -203,6 +203,7 @@ you can do so with a simple environment variable, instead of editing the -f [bare|rdoc|markdown], Render Schema Infomation as plain/RDoc/Markdown --format --force Force new annotations even if there are no changes. + --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)'` diff --git a/bin/annotate b/bin/annotate index 0bf4db646..3e0d8ad39 100755 --- a/bin/annotate +++ b/bin/annotate @@ -22,6 +22,7 @@ has_set_position = {} target_action = :do_annotations positions = %w(before top after bottom) +# rubocop:disable Metrics/BlockLength OptionParser.new do |opts| opts.banner = 'Usage: annotate [options] [model_file]*' @@ -170,6 +171,10 @@ OptionParser.new do |opts| 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 @@ -202,6 +207,7 @@ OptionParser.new do |opts| ENV['with_comment'] = 'true' end end.parse! +# rubocop:enable Metrics/BlockLength options = Annotate.setup_options( is_rake: ENV['is_rake'] && !ENV['is_rake'].empty? diff --git a/lib/annotate.rb b/lib/annotate.rb index 4a0ebb5c0..27e585773 100644 --- a/lib/annotate.rb +++ b/lib/annotate.rb @@ -29,8 +29,8 @@ module Annotate FLAG_OPTIONS = [ :show_indexes, :simple_indexes, :include_version, :exclude_tests, :exclude_fixtures, :exclude_factories, :ignore_model_sub_dir, - :format_bare, :format_rdoc, :format_markdown, :sort, :force, :trace, - :timestamp, :exclude_serializers, :classified_sort, + :format_bare, :format_rdoc, :format_markdown, :sort, :force, :frozen, + :trace, :timestamp, :exclude_serializers, :classified_sort, :show_foreign_keys, :show_complete_foreign_keys, :exclude_scaffolds, :exclude_controllers, :exclude_helpers, :exclude_sti_subclasses, :ignore_unknown_models, :with_comment diff --git a/lib/annotate/annotate_models.rb b/lib/annotate/annotate_models.rb index 61c535a3f..6a46d0f9f 100644 --- a/lib/annotate/annotate_models.rb +++ b/lib/annotate/annotate_models.rb @@ -513,6 +513,8 @@ def annotate_one_file(file_name, info_block, position, options = {}) return false if old_columns == new_columns && !options[:force] + abort "annotate error. #{file_name} needs to be updated, but annotate was run with `--frozen`." if options[:frozen] + # Replace inline the old schema info with the new schema info wrapper_open = options[:wrapper_open] ? "# #{options[:wrapper_open]}\n" : "" wrapper_close = options[:wrapper_close] ? "# #{options[:wrapper_close]}\n" : "" diff --git a/lib/generators/annotate/templates/auto_annotate_models.rake b/lib/generators/annotate/templates/auto_annotate_models.rake index 6d5d65513..eea2aa859 100644 --- a/lib/generators/annotate/templates/auto_annotate_models.rake +++ b/lib/generators/annotate/templates/auto_annotate_models.rake @@ -42,6 +42,7 @@ if Rails.env.development? 'format_markdown' => 'false', 'sort' => 'false', 'force' => 'false', + 'frozen' => 'false', 'classified_sort' => 'true', 'trace' => 'false', 'wrapper_open' => nil, diff --git a/lib/tasks/annotate_models.rake b/lib/tasks/annotate_models.rake index 0440a8917..1d4ab21bc 100644 --- a/lib/tasks/annotate_models.rake +++ b/lib/tasks/annotate_models.rake @@ -39,6 +39,7 @@ task annotate_models: :environment do options[:format_markdown] = Annotate.true?(ENV['format_markdown']) options[:sort] = Annotate.true?(ENV['sort']) options[:force] = Annotate.true?(ENV['force']) + options[:frozen] = Annotate.true?(ENV['frozen']) options[:classified_sort] = Annotate.true?(ENV['classified_sort']) options[:trace] = Annotate.true?(ENV['trace']) options[:wrapper_open] = Annotate.fallback(ENV['wrapper_open'], ENV['wrapper']) diff --git a/spec/annotate/annotate_models_spec.rb b/spec/annotate/annotate_models_spec.rb index 48838feaa..01db9ce99 100644 --- a/spec/annotate/annotate_models_spec.rb +++ b/spec/annotate/annotate_models_spec.rb @@ -1768,6 +1768,25 @@ class User < ActiveRecord::Base expect(error_output).to include("/user.rb:2:in `'") end end + + describe 'frozen option' do + it "should abort without existing annotation when frozen: true " do + expect { annotate_one_file frozen: true }.to raise_error SystemExit, /user.rb needs to be updated, but annotate was run with `--frozen`./ + end + + it "should abort with different annotation when frozen: true " do + annotate_one_file + another_schema_info = AnnotateModels.get_schema_info(mock_class(:users, :id, [mock_column(:id, :integer)]), '== Schema Info') + @schema_info = another_schema_info + + expect { annotate_one_file frozen: true }.to raise_error SystemExit, /user.rb needs to be updated, but annotate was run with `--frozen`./ + end + + it "should NOT abort with same annotation when frozen: true " do + annotate_one_file + expect { annotate_one_file frozen: true }.not_to raise_error + end + end end describe '.annotate_model_file' do