diff --git a/lib/annotate_rb/model_annotator/index_annotation/index_component.rb b/lib/annotate_rb/model_annotator/index_annotation/index_component.rb index 25243f12..cdade2b9 100644 --- a/lib/annotate_rb/model_annotator/index_annotation/index_component.rb +++ b/lib/annotate_rb/model_annotator/index_annotation/index_component.rb @@ -136,13 +136,23 @@ def to_markdown def columns_info Array(index.columns).map do |col| - if index.try(:orders) && index.orders[col.to_s] - "#{col} #{index.orders[col.to_s].upcase}" - else - col.to_s.gsub("\r", '\r').gsub("\n", '\n') - end + column = col.to_s.gsub("\r", '\r').gsub("\n", '\n') + opclass = column_option(:opclasses, col) + order = column_option(:orders, col) + + [column, opclass, order&.upcase].compact.join(" ") end end + + # ActiveRecord condenses per column index options (`opclasses`, `orders`) + # into a single value when every column shares the same one, so the + # option can either be a Hash keyed by column or a bare value. + def column_option(option, col) + value = index.try(option) + value = value[col.to_s] if value.is_a?(Hash) + + value.presence&.to_s + end end end end diff --git a/spec/lib/annotate_rb/model_annotator/index_annotation/annotation_builder_spec.rb b/spec/lib/annotate_rb/model_annotator/index_annotation/annotation_builder_spec.rb index d180f939..c753f2e6 100644 --- a/spec/lib/annotate_rb/model_annotator/index_annotation/annotation_builder_spec.rb +++ b/spec/lib/annotate_rb/model_annotator/index_annotation/annotation_builder_spec.rb @@ -67,6 +67,103 @@ end end + context "index has the same order for every column" do + let(:indexes) do + [ + mock_index("index_rails_02e851e3b8", + columns: %w[firstname surname], + orders: :desc) + ] + end + + let(:expected_result) do + <<~EOS.strip + # + # Indexes + # + # index_rails_02e851e3b8 (firstname DESC,surname DESC) + EOS + end + + it "matches the expected result" do + expect(default_format).to eq(expected_result) + end + end + + context "index includes an operator class" do + let(:indexes) do + [ + mock_index("index_rails_02e851e3b7", columns: ["id"]), + mock_index("index_rails_02e851e3b8", + columns: %w[firstname surname], + opclasses: {"surname" => :text_pattern_ops}), + mock_index("index_rails_02e851e3b9", + columns: %w[firstname surname], + opclasses: {"firstname" => :text_pattern_ops, "surname" => :text_pattern_ops}, + orders: {"surname" => :desc}) + ] + end + + let(:expected_default) do + <<~EOS.strip + # + # Indexes + # + # index_rails_02e851e3b7 (id) + # index_rails_02e851e3b8 (firstname,surname text_pattern_ops) + # index_rails_02e851e3b9 (firstname text_pattern_ops,surname text_pattern_ops DESC) + EOS + end + + let(:expected_markdown) do + <<~EOS.strip + # + # ### Indexes + # + # * `index_rails_02e851e3b7`: + # * **`id`** + # * `index_rails_02e851e3b8`: + # * **`firstname`** + # * **`surname text_pattern_ops`** + # * `index_rails_02e851e3b9`: + # * **`firstname text_pattern_ops`** + # * **`surname text_pattern_ops DESC`** + EOS + end + + it "includes the operator class in default format" do + expect(default_format).to eq(expected_default) + end + + it "includes the operator class in markdown format" do + expect(markdown_format).to eq(expected_markdown) + end + end + + context "index has the same operator class for every column" do + let(:indexes) do + [ + mock_index("index_rails_02e851e3b8", + columns: %w[name], + opclasses: :gist_trgm_ops, + using: "gist") + ] + end + + let(:expected_result) do + <<~EOS.strip + # + # Indexes + # + # index_rails_02e851e3b8 (name gist_trgm_ops) USING gist + EOS + end + + it "matches the expected result" do + expect(default_format).to eq(expected_result) + end + end + context "index includes a where clause" do let(:indexes) do [ diff --git a/spec/support/annotate_test_helpers.rb b/spec/support/annotate_test_helpers.rb index 2e888247..cd8a06e2 100644 --- a/spec/support/annotate_test_helpers.rb +++ b/spec/support/annotate_test_helpers.rb @@ -23,6 +23,7 @@ def mock_index(name, params = {}) unique: params[:unique] || false, nulls_not_distinct: params[:nulls_not_distinct] || false, orders: params[:orders] || {}, + opclasses: params[:opclasses] || {}, where: params[:where], using: params[:using], comment: params[:comment])