Skip to content

Commit

Permalink
Fix updating of indexes containing escaped characters (#156)
Browse files Browse the repository at this point in the history
There are a number of different mechanisms with
[String#sub](https://ruby-doc.org/core-2.4.5/String.html#method-i-sub)
that pertain to the matching of backreferences and capture groups when
using either the String or Hash type args for the replacement arg.

>If replacement is a String that looks like a pattern's capture group
but is actually not a pattern capture group e.g. "\'", then it will have
to be preceded by two backslashes like so "\\'".

When an index contains unescaped characters, those are being incorrectly
interpreted as capture groups. Using the block version of #sub avoids
this.

For example, here's the behaviour we see with an index containing
special characters that need escaping.

This becomes a problem given that the issue is in the `Updater` itself;
we get stuck in a loop where annotation changes are always being
detected, so a CI step with `--frozen` will always fail.
  • Loading branch information
antonivanopoulos authored Oct 14, 2024
1 parent 30a2b41 commit 963bbc7
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/annotate_rb/model_annotator/annotated_file/updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def update

new_annotation = wrapped_content(@new_annotations)

_content = @file_content.sub(@parsed_file.annotations, new_annotation)
_content = @file_content.sub(@parsed_file.annotations) { new_annotation }
end

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,61 @@ class User < ApplicationRecord
end
end

context "with an index change containing escaped characters" do
let(:file_content) do
<<~FILE
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# foreign_thing_id :integer not null
#
class User < ApplicationRecord
end
FILE
end
let(:new_annotations) do
<<~ANNOTATIONS
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# foreign_thing_id :integer not null
#
# Indexes
#
# index_rails_02e851e3b8 (another_column) WHERE value IS LIKE '\\\\%'
#
ANNOTATIONS
end

let(:options) { AnnotateRb::Options.new({position_in_class: "before", show_foreign_keys: true}) }

let(:expected_content) do
<<~CONTENT
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# foreign_thing_id :integer not null
#
# Indexes
#
# index_rails_02e851e3b8 (another_column) WHERE value IS LIKE '\\\\%'
#
class User < ApplicationRecord
end
CONTENT
end

it "returns the updated annotated file" do
is_expected.to eq(expected_content)
end
end

context 'when position is "after" for the existing annotation but position is "before" for the new annotation' do
let(:file_content) do
<<~FILE
Expand Down

0 comments on commit 963bbc7

Please sign in to comment.