Skip to content

Commit ecc5c9e

Browse files
committed
Fixes updating columns when using alternative formats
Updates `column_pattern` in `AnnotateModels.annotate_one_file` to support RDoc and Yard doc formats. `column_pattern` is responsible for searching for existing annotations in the file - if the patten is not matched in file, annotations are not updated. Since the previous regular expression did not match the Yard (`@!`) or RDoc (`**<attributed>**::`), when attempting to update annotations for a model, it would look like there were no changes since parsing the annotation blocks with the regular expression would return nothing.
1 parent 8666d89 commit ecc5c9e

File tree

2 files changed

+92
-1
lines changed

2 files changed

+92
-1
lines changed

lib/annotate/annotate_models.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ def get_foreign_key_info(klass, options = {})
351351
# :force<Symbol>:: whether to update the file even if it doesn't seem to need it.
352352
# :position_in_*<Symbol>:: where to place the annotated section in fixture or model file,
353353
# :before, :top, :after or :bottom. Default is :before.
354+
# :format_bare<Boolean>:: whether to format annotations using default, bare syntax
355+
# :format_markdown<Boolean>:: whether to format annotations using Markdown syntax
356+
# :format_rdoc<Boolean>:: whether to format annotations using RDoc syntax
357+
# :format_yard<Boolean>:: whether to format annotations using Yard syntax
354358
#
355359
def annotate_one_file(file_name, info_block, position, options = {})
356360
return false unless File.exist?(file_name)
@@ -362,7 +366,7 @@ def annotate_one_file(file_name, info_block, position, options = {})
362366
old_header = old_content.match(header_pattern).to_s
363367
new_header = info_block.match(header_pattern).to_s
364368

365-
column_pattern = /^#[\t ]+[\w\*\.`]+[\t ]+.+$/
369+
column_pattern = /^#[\t ]+[\w\*\.\`\@\!\:]+[\t ]+.+$/
366370
old_columns = old_header && old_header.scan(column_pattern).sort
367371
new_columns = new_header && new_header.scan(column_pattern).sort
368372

spec/lib/annotate/annotate_models_spec.rb

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,6 +2515,93 @@ def annotate_one_file(options = {})
25152515
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
25162516
end
25172517
end
2518+
2519+
context 'adding a new field' do
2520+
let(:class_name) { :users }
2521+
let(:primary_key) { :id }
2522+
let(:original_columns) do
2523+
[
2524+
mock_column(primary_key, :integer),
2525+
mock_column(:name, :string)
2526+
]
2527+
end
2528+
2529+
before do
2530+
klass = mock_class(class_name, primary_key, original_columns)
2531+
@schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', options)
2532+
annotate_one_file(options)
2533+
2534+
# confirm we initialized annotaions in file before checking for changes
2535+
expect(@schema_info).not_to be_empty
2536+
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
2537+
end
2538+
2539+
context 'when option "format_bare" is true' do
2540+
let :options do
2541+
{ format_bare: true }
2542+
end
2543+
2544+
it 'updates the fields list to include the new column' do
2545+
new_column_list = original_columns + [mock_column(:new_column, :string)]
2546+
klass = mock_class(class_name, primary_key, new_column_list)
2547+
@schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', options)
2548+
annotate_one_file(options)
2549+
2550+
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
2551+
end
2552+
end
2553+
2554+
context 'when option "format_yard" is true' do
2555+
let :options do
2556+
{ format_yard: true }
2557+
end
2558+
2559+
it 'updates the fields list to include the new column' do
2560+
new_column_list = original_columns + [mock_column(:new_column, :string)]
2561+
klass = mock_class(class_name, primary_key, new_column_list)
2562+
@schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', options)
2563+
annotate_one_file(options)
2564+
2565+
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
2566+
end
2567+
end
2568+
2569+
context 'when option "format_rdoc" is true' do
2570+
let :options do
2571+
{ format_rdoc: true }
2572+
end
2573+
2574+
it 'updates the fields list to include the new column' do
2575+
new_column_list = original_columns + [mock_column(:new_column, :string)]
2576+
klass = mock_class(class_name, primary_key, new_column_list)
2577+
@schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', options)
2578+
annotate_one_file(options)
2579+
2580+
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
2581+
end
2582+
end
2583+
2584+
context 'when option "format_markdown" is true' do
2585+
let :options do
2586+
{ format_markdown: true }
2587+
end
2588+
2589+
it 'updates the fields list to include the new column' do
2590+
# The new column name must be shorter than the existing columns
2591+
# becuase markdown formatting adds additional spacing. If the
2592+
# column name is long, the header row has space added triggering a
2593+
# difference even if we don't properly check the columns. By having
2594+
# a shorter column name we are testing our column list comparison
2595+
# and not an unintentional resizing.
2596+
new_column_list = original_columns + [mock_column(:a, :string)]
2597+
klass = mock_class(class_name, primary_key, new_column_list)
2598+
@schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', options)
2599+
annotate_one_file(options)
2600+
2601+
expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")
2602+
end
2603+
end
2604+
end
25182605
end
25192606

25202607
describe 'with existing annotation => :before' do

0 commit comments

Comments
 (0)