Skip to content

Commit 9cadf61

Browse files
committed
Warn about changing query_constraints: behavior
This commit adds a deprecation warning for the `query_constraints:` association option. This option will change behavior in the future versions of Rails and applications are encouraged to switch to `foreign_key:` to preserve the current behavior.
1 parent dcfabdb commit 9cadf61

16 files changed

+92
-30
lines changed

activerecord/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Association option `query_constraints` is deprecated in favor of `foreign_key`.
2+
3+
*Nikita Vasilevsky*
4+
15
* Add ENV["SKIP_TEST_DATABASE_TRUNCATE"] flag to speed up multi-process test runs on large DBs when all tests run within default txn. (This cuts ~10s from the test run of HEY when run by 24 processes against the 178 tables, since ~4,000 table truncates can then be skipped.)
26

37
*DHH*

activerecord/lib/active_record/fixtures.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,8 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
498498
# # app/models/book_orders.rb
499499
# class BookOrder < ApplicationRecord
500500
# self.primary_key = [:shop_id, :id]
501-
# belongs_to :order, query_constraints: [:shop_id, :order_id]
502-
# belongs_to :book, query_constraints: [:author_id, :book_id]
501+
# belongs_to :order, foreign_key: [:shop_id, :order_id]
502+
# belongs_to :book, foreign_key: [:author_id, :book_id]
503503
# end
504504
#
505505
# <code></code>

activerecord/lib/active_record/reflection.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,13 @@ def initialize(name, scope, options, active_record)
522522
@foreign_key = nil
523523
@association_foreign_key = nil
524524
@association_primary_key = nil
525+
if options[:query_constraints]
526+
ActiveRecord.deprecator.warn <<~MSG.squish
527+
Setting `query_constraints:` option on `#{active_record}.#{macro} :#{name}` is deprecated.
528+
To maintain current behavior, use the `foreign_key` option instead.
529+
MSG
530+
end
531+
525532
# If the foreign key is an array, set query constraints options and don't use the foreign key
526533
if options[:foreign_key].is_a?(Array)
527534
options[:query_constraints] = options.delete(:foreign_key)

activerecord/test/cases/associations_test.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,28 @@ def test_nullify_composite_has_many_through_association
461461
assert_empty(blog_post.reload.tags)
462462
assert_not_predicate Sharded::BlogPostTag.where(blog_post_id: blog_post.id, blog_id: blog_post.blog_id), :exists?
463463
end
464+
465+
def test_using_query_constraints_warns_about_changing_behavior
466+
has_many_expected_message = <<~MSG.squish
467+
Setting `query_constraints:` option on `Sharded::BlogPost.has_many :qc_deprecated_comments` is deprecated.
468+
To maintain current behavior, use the `foreign_key` option instead.
469+
MSG
470+
471+
assert_deprecated(has_many_expected_message, ActiveRecord.deprecator) do
472+
Sharded::BlogPost.has_many :qc_deprecated_comments,
473+
class_name: "Sharded::Comment", query_constraints: [:blog_id, :blog_post_id]
474+
end
475+
476+
belongs_to_expected_message = <<~MSG.squish
477+
Setting `query_constraints:` option on `Sharded::Comment.belongs_to :qc_deprecated_blog_post` is deprecated.
478+
To maintain current behavior, use the `foreign_key` option instead.
479+
MSG
480+
481+
assert_deprecated(belongs_to_expected_message, ActiveRecord.deprecator) do
482+
Sharded::Comment.belongs_to :qc_deprecated_blog_post,
483+
class_name: "Sharded::Blog", query_constraints: [:blog_id, :blog_post_id]
484+
end
485+
end
464486
end
465487

466488
class AssociationProxyTest < ActiveRecord::TestCase

activerecord/test/cases/reflection_test.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,35 @@ def test_belongs_to_reflection_with_query_constraints_infers_correct_foreign_key
628628
assert_equal ["blog_id", "blog_post_id"], blog_post_foreign_key
629629
end
630630

631+
def test_using_query_constraints_warns_about_changing_behavior
632+
has_many_expected_message = <<~MSG.squish
633+
Setting `query_constraints:` option on `Firm.has_many :clients` is deprecated.
634+
To maintain current behavior, use the `foreign_key` option instead.
635+
MSG
636+
637+
assert_deprecated(has_many_expected_message, ActiveRecord.deprecator) do
638+
ActiveRecord::Reflection.create(:has_many, :clients, nil, { query_constraints: [:firm_id, :firm_name] }, Firm)
639+
end
640+
641+
has_one_expected_message = <<~MSG.squish
642+
Setting `query_constraints:` option on `Firm.has_one :account` is deprecated.
643+
To maintain current behavior, use the `foreign_key` option instead.
644+
MSG
645+
646+
assert_deprecated(has_one_expected_message, ActiveRecord.deprecator) do
647+
ActiveRecord::Reflection.create(:has_one, :account, nil, { query_constraints: [:firm_id, :firm_name] }, Firm)
648+
end
649+
650+
belongs_to_expected_message = <<~MSG.squish
651+
Setting `query_constraints:` option on `Firm.belongs_to :client` is deprecated.
652+
To maintain current behavior, use the `foreign_key` option instead.
653+
MSG
654+
655+
assert_deprecated(belongs_to_expected_message, ActiveRecord.deprecator) do
656+
ActiveRecord::Reflection.create(:belongs_to, :client, nil, { query_constraints: [:firm_id, :firm_name] }, Firm)
657+
end
658+
end
659+
631660
private
632661
def assert_reflection(klass, association, options)
633662
assert reflection = klass.reflect_on_association(association)

activerecord/test/models/cpk/book.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ class Book < ActiveRecord::Base
55
attr_accessor :fail_destroy
66

77
self.table_name = :cpk_books
8-
belongs_to :order, autosave: true, query_constraints: [:shop_id, :order_id], counter_cache: true
9-
belongs_to :order_explicit_fk_pk, class_name: "Cpk::Order", query_constraints: [:shop_id, :order_id], primary_key: [:shop_id, :id]
8+
belongs_to :order, autosave: true, foreign_key: [:shop_id, :order_id], counter_cache: true
9+
belongs_to :order_explicit_fk_pk, class_name: "Cpk::Order", foreign_key: [:shop_id, :order_id], primary_key: [:shop_id, :id]
1010
belongs_to :author, class_name: "Cpk::Author"
1111

12-
has_many :chapters, query_constraints: [:author_id, :book_id]
12+
has_many :chapters, foreign_key: [:author_id, :book_id]
1313

1414
before_destroy :prevent_destroy_if_set
1515

@@ -27,17 +27,17 @@ class BrokenBook < Book
2727
end
2828

2929
class BrokenBookWithNonCpkOrder < Book
30-
belongs_to :order, class_name: "Cpk::NonCpkOrder", query_constraints: [:shop_id, :order_id]
30+
belongs_to :order, class_name: "Cpk::NonCpkOrder", foreign_key: [:shop_id, :order_id]
3131
end
3232

3333
class NonCpkBook < Book
3434
self.primary_key = :id
3535

36-
belongs_to :non_cpk_order, query_constraints: [:order_id]
36+
belongs_to :non_cpk_order, foreign_key: [:order_id]
3737
end
3838

3939
class NullifiedBook < Book
40-
has_one :chapter, query_constraints: [:author_id, :book_id], dependent: :nullify
40+
has_one :chapter, foreign_key: [:author_id, :book_id], dependent: :nullify
4141
end
4242

4343
class BookWithOrderAgreements < Book

activerecord/test/models/cpk/chapter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ class Chapter < ActiveRecord::Base
77
# to be shared between different databases
88
self.primary_key = [:author_id, :id]
99

10-
belongs_to :book, query_constraints: [:author_id, :book_id]
10+
belongs_to :book, foreign_key: [:author_id, :book_id]
1111
end
1212
end

activerecord/test/models/cpk/comment.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Cpk
44
class Comment < ActiveRecord::Base
55
self.table_name = :cpk_comments
6-
belongs_to :commentable, class_name: "Cpk::Post", query_constraints: %i[commentable_title commentable_author], polymorphic: true
7-
belongs_to :post, class_name: "Cpk::Post", query_constraints: %i[commentable_title commentable_author]
6+
belongs_to :commentable, class_name: "Cpk::Post", foreign_key: %i[commentable_title commentable_author], polymorphic: true
7+
belongs_to :post, class_name: "Cpk::Post", foreign_key: %i[commentable_title commentable_author]
88
end
99
end

activerecord/test/models/cpk/order.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class Order < ActiveRecord::Base
1010
alias_attribute :id_value, :id
1111

1212
has_many :order_agreements
13-
has_many :books, query_constraints: [:shop_id, :order_id]
14-
has_one :book, query_constraints: [:shop_id, :order_id]
13+
has_many :books, foreign_key: [:shop_id, :order_id]
14+
has_one :book, foreign_key: [:shop_id, :order_id]
1515
has_many :order_tags
1616
has_many :tags, through: :order_tags
1717
end
@@ -26,8 +26,8 @@ class BrokenOrder < Order
2626
class OrderWithSpecialPrimaryKey < Order
2727
self.primary_key = [:shop_id, :status]
2828

29-
has_many :books, query_constraints: [:shop_id, :status]
30-
has_one :book, query_constraints: [:shop_id, :status]
29+
has_many :books, foreign_key: [:shop_id, :status]
30+
has_one :book, foreign_key: [:shop_id, :status]
3131
end
3232

3333
class BrokenOrderWithNonCpkBooks < Order
@@ -46,7 +46,7 @@ class OrderWithPrimaryKeyAssociatedBook < Order
4646
end
4747

4848
class OrderWithNullifiedBook < Order
49-
has_one :book, query_constraints: [:shop_id, :order_id], dependent: :nullify
49+
has_one :book, foreign_key: [:shop_id, :order_id], dependent: :nullify
5050
end
5151

5252
class OrderWithSingularBookChapters < Order

activerecord/test/models/cpk/post.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
module Cpk
44
class Post < ActiveRecord::Base
55
self.table_name = :cpk_posts
6-
has_many :comments, class_name: "Cpk::Comment", query_constraints: %i[commentable_title commentable_author], as: :commentable
6+
has_many :comments, class_name: "Cpk::Comment", foreign_key: %i[commentable_title commentable_author], as: :commentable
77
end
88
end

0 commit comments

Comments
 (0)