diff --git a/lib/annotate_rb/model_annotator/foreign_key_annotation/foreign_key_component_builder.rb b/lib/annotate_rb/model_annotator/foreign_key_annotation/foreign_key_component_builder.rb index 71afcfd1..8ebf820b 100644 --- a/lib/annotate_rb/model_annotator/foreign_key_annotation/foreign_key_component_builder.rb +++ b/lib/annotate_rb/model_annotator/foreign_key_annotation/foreign_key_component_builder.rb @@ -32,6 +32,12 @@ def constraints_info constraints_info = "" constraints_info += "ON DELETE => #{foreign_key.on_delete} " if foreign_key.on_delete constraints_info += "ON UPDATE => #{foreign_key.on_update} " if foreign_key.on_update + if foreign_key.respond_to?(:deferrable) && foreign_key.deferrable + # Rails 7.0's extract_foreign_key_deferrable returns `true` for the initially-immediate case; + # 7.1+ normalized this to `:immediate`. Map `true` back to IMMEDIATE so we don't emit "INITIALLY TRUE". + initially = (foreign_key.deferrable == true) ? "IMMEDIATE" : foreign_key.deferrable.to_s.upcase + constraints_info += "DEFERRABLE INITIALLY #{initially} " + end constraints_info.strip end end diff --git a/spec/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder_spec.rb b/spec/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder_spec.rb index f46db1bb..765f8145 100644 --- a/spec/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder_spec.rb +++ b/spec/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder_spec.rb @@ -122,6 +122,34 @@ it { expect(default_format).to eq(expected_output) } end + context "with a deferrable foreign key" do + let(:foreign_keys) do + [ + mock_foreign_key("fk_rails_immediate", + "immediate_thing_id", + "immediate_things", + "id", + deferrable: :immediate), + mock_foreign_key("fk_rails_deferred", + "deferred_thing_id", + "deferred_things", + "id", + deferrable: :deferred) + ] + end + let(:expected_output) do + <<~OUTPUT.strip + # + # Foreign Keys + # + # fk_rails_deferred (deferred_thing_id => deferred_things.id) DEFERRABLE INITIALLY DEFERRED + # fk_rails_immediate (immediate_thing_id => immediate_things.id) DEFERRABLE INITIALLY IMMEDIATE + OUTPUT + end + + it { expect(default_format).to eq(expected_output) } + end + context "with a composite foreign key" do let(:foreign_keys) do [ diff --git a/spec/support/annotate_test_helpers.rb b/spec/support/annotate_test_helpers.rb index f2255029..2e888247 100644 --- a/spec/support/annotate_test_helpers.rb +++ b/spec/support/annotate_test_helpers.rb @@ -35,7 +35,8 @@ def mock_foreign_key(name, from_column, to_table, to_column = "id", constraints to_table: to_table, primary_key: to_column, on_delete: constraints[:on_delete], - on_update: constraints[:on_update]) + on_update: constraints[:on_update], + deferrable: constraints[:deferrable]) end def mock_connection(indexes = [], foreign_keys = [], check_constraints = [], options = {})