Skip to content

Commit 8caa042

Browse files
committed
Add inverse_of to state/address, add FK constraint
For the database, a state is optional on an address. What this commit ensures is that any state ID entered into the `state_id` column on `spree_addresses` is actually present in the `spree_states` table.
1 parent 32d308c commit 8caa042

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

core/app/models/spree/state.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Spree
44
class State < Spree::Base
55
belongs_to :country, class_name: 'Spree::Country'
6-
has_many :addresses, dependent: :nullify
6+
has_many :addresses, dependent: :nullify, inverse_of: :state
77

88
validates :name, presence: true
99

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
class AddStateForeignKeys < ActiveRecord::Migration[7.0]
4+
FOREIGN_KEY_VIOLATION_ERRORS = %w[PG::ForeignKeyViolation Mysql2::Error SQLite3::ConstraintException]
5+
6+
def up
7+
# Uncomment the following code to remove orphaned records if this migration fails
8+
#
9+
# say_with_time "Resetting state IDs on addresses where the state record is no longer present" do
10+
# Spree::Address.where.not(state_id: nil).left_joins(:state).where(spree_states: { id: nil }).update_all(state_id: nil)
11+
# end
12+
13+
add_foreign_key :spree_addresses, :spree_states, column: :state_id, null: true, on_delete: :restrict
14+
rescue ActiveRecord::StatementInvalid => e
15+
if e.cause.class.name.in?(FOREIGN_KEY_VIOLATION_ERRORS)
16+
say <<~MSG
17+
⚠️ Foreign key constraint failed when adding :spree_addresses => :spree_states.
18+
To fix this:
19+
1. Uncomment the code that removes orphaned records.
20+
2. Rerun the migration.
21+
Offending error: #{e.cause.class} - #{e.cause.message}
22+
MSG
23+
end
24+
raise
25+
end
26+
27+
def down
28+
remove_foreign_key :spree_addresses, :spree_states, column: :state_id, null: true, on_delete: :restrict
29+
end
30+
end

0 commit comments

Comments
 (0)