Skip to content

Commit c6d0ef5

Browse files
committed
Refactor ActiveRecord::SignedId to not rely on relation delegation
Ref: rails#50396 Ref: rails#51776 `ActiveRecord::Relation` automatically delegates missing methods to the model class wrapped in a `scoping { }` block. This is to support scoping in user defined class methods. The problem however is that it's very error prone for the framework, because we can mistakenly call model methods from inside `Relation` and not realized we're applying a global scope. In the best case scenario it's just a waste of performance, but it can also lead to bugs like rails#51775 I'm planning to restrict this automatic delegation to methods defined in childs of `ActiveRecord::Base` only: rails#50396 but for this to work we must first refactor any Rails code that rely on it.
1 parent 007a609 commit c6d0ef5

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

activerecord/lib/active_record/relation.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def exec_explain(&block)
6666

6767
include Enumerable
6868
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation
69+
include SignedId::RelationMethods
6970

7071
attr_reader :table, :klass, :loaded, :predicate_builder
7172
attr_accessor :skip_preloading_value

activerecord/lib/active_record/signed_id.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ module SignedId
1313
class_attribute :signed_id_verifier_secret, instance_writer: false
1414
end
1515

16+
module RelationMethods # :nodoc:
17+
def find_signed(...)
18+
scoping { model.find_signed(...) }
19+
end
20+
21+
def find_signed!(...)
22+
scoping { model.find_signed!(...) }
23+
end
24+
end
25+
1626
module ClassMethods
1727
# Lets you find a record based on a signed id that's safe to put into the world without risk of tampering.
1828
# This is particularly useful for things like password reset or email verification, where you want

0 commit comments

Comments
 (0)