Permalink
Browse files

Fix setting a polymorphic association's attributes to nil and saving,…

… if that association had been non-nil and loaded.

This raised a nil deref, because the stale_state test returned true (the target was no longer valid) and so #find_target called #scope, which ran klass.all - which failed because #klass is now nil.

This only happened if saving the record holding this polymorphic association, as opposed to say referencing the association, because the latter is implemented by the SingularAssociation#reader method which called #reload if the target was stale.  This patch does something similar, but a bit less radical (calling reset).
  • Loading branch information...
1 parent f020f30 commit 0ab147e62993fbaf08399a36e4f9906f4c42d8cd @willbryant committed Aug 22, 2014
@@ -135,7 +135,8 @@ def target_scope
# ActiveRecord::RecordNotFound is rescued within the method, and it is
# not reraised. The proxy is \reset and +nil+ is the return value.
def load_target
- @target = find_target if (@stale_state && stale_target?) || find_target?
+ reset if @stale_state && stale_target?
+ @target = find_target if find_target?
loaded! unless loaded?
target
@@ -465,6 +465,15 @@ def test_polymorphic_setting_foreign_key_after_nil_target_loaded
assert_equal members(:groucho), sponsor.sponsorable
end
+ def test_polymorphic_autosaving_nil_target_after_non_nil_target_loaded
+ sponsor = Sponsor.new(sponsorable_id: 1, sponsorable_type: "Member")
+ sponsor.sponsorable
+ sponsor.sponsorable_id = nil
+ sponsor.sponsorable_type = nil
+
+ sponsor.save!
+ end
+
def test_dont_find_target_when_foreign_key_is_null
tagging = taggings(:thinking_general)
assert_queries(0) { tagging.super_tag }

0 comments on commit 0ab147e

Please sign in to comment.