Skip to content

Commit acb9cc8

Browse files
authored
Merge pull request #6271 from mamhoff/foreign-key-inverse-of-product-taxons
Add dependent/inverse_of options to product-related models
2 parents db99cba + 04493b1 commit acb9cc8

11 files changed

+195
-15
lines changed

.rubocop_todo.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2025-06-18 13:16:56 UTC using RuboCop version 1.76.0.
3+
# on 2025-06-18 14:45:47 UTC using RuboCop version 1.76.0.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -332,7 +332,7 @@ Rails/FilePath:
332332
- 'core/lib/spree/testing_support/dummy_app.rb'
333333
- 'sample/lib/spree/sample.rb'
334334

335-
# Offense count: 57
335+
# Offense count: 53
336336
# Configuration parameters: Include.
337337
# Include: **/app/models/**/*.rb
338338
Rails/HasManyOrHasOneDependent:
@@ -374,7 +374,7 @@ Rails/IndexWith:
374374
- 'core/lib/spree/core/search/variant.rb'
375375
- 'core/lib/spree/preferences/preferable.rb'
376376

377-
# Offense count: 27
377+
# Offense count: 26
378378
# Configuration parameters: IgnoreScopes, Include.
379379
# Include: **/app/models/**/*.rb
380380
Rails/InverseOf:

core/app/models/spree/classification.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ module Spree
44
class Classification < Spree::Base
55
self.table_name = 'spree_products_taxons'
66
acts_as_list scope: :taxon
7-
belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications, touch: true, optional: true
8-
belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications, touch: true, optional: true
7+
belongs_to :product, class_name: "Spree::Product", inverse_of: :classifications, touch: true
8+
belongs_to :taxon, class_name: "Spree::Taxon", inverse_of: :classifications, touch: true
99

1010
# For https://github.com/spree/spree/issues/3494
1111
validates :taxon_id, uniqueness: { scope: :product_id, message: :already_linked }

core/app/models/spree/product.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Product < Spree::Base
2323

2424
has_many :product_properties, dependent: :destroy, inverse_of: :product
2525
has_many :properties, through: :product_properties
26-
has_many :variant_property_rules
26+
has_many :variant_property_rules, dependent: :destroy
2727
has_many :variant_property_rule_values, through: :variant_property_rules, source: :values
2828
has_many :variant_property_rule_conditions, through: :variant_property_rules, source: :conditions
2929

@@ -38,12 +38,14 @@ class Product < Spree::Base
3838
-> { where(is_master: true).with_discarded },
3939
inverse_of: :product,
4040
class_name: 'Spree::Variant',
41-
autosave: true
41+
autosave: true,
42+
dependent: false
4243

4344
has_many :variants,
4445
-> { where(is_master: false).order(:position) },
4546
inverse_of: :product,
46-
class_name: 'Spree::Variant'
47+
class_name: 'Spree::Variant',
48+
dependent: false
4749

4850
has_many :variants_including_master,
4951
-> { order(:position) },

core/app/models/spree/product_option_type.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
module Spree
44
class ProductOptionType < Spree::Base
5-
belongs_to :product, class_name: 'Spree::Product', inverse_of: :product_option_types, touch: true, optional: true
6-
belongs_to :option_type, class_name: 'Spree::OptionType', inverse_of: :product_option_types, optional: true
5+
belongs_to :product, class_name: 'Spree::Product', inverse_of: :product_option_types, touch: true
6+
belongs_to :option_type, class_name: 'Spree::OptionType', inverse_of: :product_option_types
77
acts_as_list scope: :product
88
end
99
end

core/app/models/spree/product_property.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ class ProductProperty < Spree::Base
66

77
acts_as_list scope: :product
88

9-
belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :product_properties, optional: true
10-
belongs_to :property, class_name: 'Spree::Property', inverse_of: :product_properties, optional: true
9+
belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :product_properties
10+
belongs_to :property, class_name: 'Spree::Property', inverse_of: :product_properties
1111

1212
self.allowed_ransackable_attributes = ['value']
1313
end

core/app/models/spree/taxonomy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class Taxonomy < Spree::Base
77
validates :name, presence: true
88
validates :name, uniqueness: true
99

10-
has_many :taxons, inverse_of: :taxonomy
11-
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy
10+
has_many :taxons, inverse_of: :taxonomy, dependent: false
11+
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy, inverse_of: false
1212

1313
after_save :set_name
1414

core/app/models/spree/variant_property_rule.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# targeted by the rule, the properties will automatically apply to the variant.
1414
module Spree
1515
class VariantPropertyRule < Spree::Base
16-
belongs_to :product, touch: true, optional: true
16+
belongs_to :product, touch: true
1717

1818
has_many :values, class_name: 'Spree::VariantPropertyRuleValue', dependent: :destroy
1919
has_many :properties, through: :values
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# frozen_string_literal: true
2+
3+
class AddFkProductsVariantPropertyRules < ActiveRecord::Migration[7.0]
4+
def up
5+
# Uncomment the following code to remove orphaned records if this migration fails
6+
#
7+
# say_with_time "Removing orphaned variant property rules (no corresponding product)" do
8+
# Spree::VariantPropertyRule.left_joins(:product).where(spree_products: { id: nil }).delete_all
9+
# end
10+
11+
add_foreign_key :spree_variant_property_rules, :spree_products, column: :product_id, null: false
12+
rescue ActiveRecord::StatementInvalid => e
13+
if e.cause.is_a?(PG::ForeignKeyViolation) || e.cause.is_a?(Mysql2::Error) || e.cause.is_a?(SQLite3::ConstraintException)
14+
Rails.logger.warn <<~MSG
15+
⚠️ Foreign key constraint failed when adding :spree_variant_property_rules => :spree_products.
16+
To fix this:
17+
1. Uncomment the code that removes orphaned records.
18+
2. Rerun the migration.
19+
Offending error: #{e.cause.class} - #{e.cause.message}
20+
MSG
21+
end
22+
raise
23+
end
24+
25+
def down
26+
remove_foreign_key :spree_variant_property_rules, :spree_products, column: :product_id, null: false
27+
end
28+
end
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# frozen_string_literal: true
2+
3+
class AddFkToProductProperties < ActiveRecord::Migration[7.0]
4+
def up
5+
# Uncomment the following code to remove orphaned records if this migration fails
6+
#
7+
# say_with_time "Removing orphaned product properties (no corresponding product)" do
8+
# Spree::ProductProperty.left_joins(:product).where(spree_products: { id: nil }).delete_all
9+
# end
10+
begin
11+
add_foreign_key :spree_product_properties, :spree_products, column: :product_id, null: false
12+
rescue ActiveRecord::StatementInvalid => e
13+
if e.cause.is_a?(PG::ForeignKeyViolation) || e.cause.is_a?(Mysql2::Error) || e.cause.is_a?(SQLite3::ConstraintException)
14+
Rails.logger.warn <<~MSG
15+
⚠️ Foreign key constraint failed when adding :spree_product_properties => :spree_products.
16+
To fix this:
17+
1. Uncomment the code that removes orphaned records.
18+
2. Rerun the migration.
19+
Offending error: #{e.cause.class} - #{e.cause.message}
20+
MSG
21+
end
22+
raise
23+
end
24+
25+
# Uncomment the following code to remove orphaned records if this migration fails
26+
#
27+
# say_with_time "Removing orphaned product properties (no corresponding property)" do
28+
# Spree::ProductProperty.left_joins(:property).where(spree_properties: { id: nil }).delete_all
29+
# end
30+
begin
31+
add_foreign_key :spree_product_properties, :spree_properties, column: :property_id, null: false
32+
rescue ActiveRecord::StatementInvalid => e
33+
if e.cause.is_a?(PG::ForeignKeyViolation) || e.cause.is_a?(Mysql2::Error) || e.cause.is_a?(SQLite3::ConstraintException)
34+
Rails.logger.warn <<~MSG
35+
⚠️ Foreign key constraint failed when adding :spree_product_properties => :spree_properties.
36+
To fix this:
37+
1. Uncomment the code that removes orphaned records.
38+
2. Rerun the migration.
39+
Offending error: #{e.cause.class} - #{e.cause.message}
40+
MSG
41+
end
42+
raise
43+
end
44+
end
45+
46+
def down
47+
remove_foreign_key :spree_product_properties, :spree_products, column: :product_id, null: false
48+
remove_foreign_key :spree_product_properties, :spree_properties, column: :property_id, null: false
49+
end
50+
end
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# frozen_string_literal: true
2+
3+
class AddFkToProductOptionTypes < ActiveRecord::Migration[7.0]
4+
def up
5+
# Uncomment the following code to remove orphaned records if this migration fails
6+
#
7+
# say_with_time "Removing orphaned product option types (no corresponding product)" do
8+
# Spree::ProductOptionType.left_joins(:product).where(spree_products: { id: nil }).delete_all
9+
# end
10+
begin
11+
add_foreign_key :spree_product_option_types, :spree_products, column: :product_id
12+
rescue ActiveRecord::StatementInvalid => e
13+
if e.cause.is_a?(PG::ForeignKeyViolation) || e.cause.is_a?(Mysql2::Error) || e.cause.is_a?(SQLite3::ConstraintException)
14+
Rails.logger.warn <<~MSG
15+
⚠️ Foreign key constraint failed when adding :spree_product_option_types => :spree_products.
16+
To fix this:
17+
1. Uncomment the code that removes orphaned records.
18+
2. Rerun the migration.
19+
Offending error: #{e.cause.class} - #{e.cause.message}
20+
MSG
21+
end
22+
raise
23+
end
24+
25+
# Uncomment the following code to remove orphaned records if this migration fails
26+
#
27+
# say_with_time "Removing orphaned product option types (no corresponding option type)" do
28+
# Spree::ProductOptionType.left_joins(:option_type).where(spree_option_types: { id: nil }).delete_all
29+
# end
30+
begin
31+
add_foreign_key :spree_product_option_types, :spree_option_types, column: :option_type_id
32+
rescue ActiveRecord::StatementInvalid => e
33+
if e.cause.is_a?(PG::ForeignKeyViolation) || e.cause.is_a?(Mysql2::Error) || e.cause.is_a?(SQLite3::ConstraintException)
34+
Rails.logger.warn <<~MSG
35+
⚠️ Foreign key constraint failed when adding :spree_product_option_types => :spree_option_types.
36+
To fix this:
37+
1. Uncomment the code that removes orphaned records.
38+
2. Rerun the migration.
39+
Offending error: #{e.cause.class} - #{e.cause.message}
40+
MSG
41+
end
42+
raise
43+
end
44+
end
45+
46+
def down
47+
remove_foreign_key :spree_product_option_types, :spree_products, column: :product_id
48+
remove_foreign_key :spree_product_option_types, :spree_option_types, column: :option_type_id
49+
end
50+
end

0 commit comments

Comments
 (0)