You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An executable test case is below. It demonstrates that find_by_id behaves differently than find(id), where(:id => id).first, and find_by(:id => id). find_by_id is raising a SystemStackError when including has_many relationships and that relationship has an after_find callback that access the parent object.
beginrequire"bundler/inline"rescueLoadError=>e
$stderr.puts"Bundler version 1.10 or later is required. Please update your Bundler"raiseeendgemfile(true)dosource"https://rubygems.org"gem"rails",github: "rails/rails"gem"sqlite3"endrequire"active_record"require"minitest/autorun"require"logger"# This connection will do for database-independent bug reports.ActiveRecord::Base.establish_connection(adapter: "sqlite3",database: ":memory:")ActiveRecord::Base.logger=Logger.new(STDOUT)ActiveRecord::Schema.definedocreate_table:foods,force: truedo |t|
endcreate_table:measurements,force: truedo |t|
t.integer:food_idt.string:namet.boolean:defaultendendclassFood < ActiveRecord::Basehas_many:measurements,:inverse_of=>:foodendclassMeasurement < ActiveRecord::Basebelongs_to:food,:inverse_of=>:measurementsafter_finddoputs"Triggered after find"self.name='serving'ifname.blank? && default? && food.present?endendclassBugTest < Minitest::Testdefsetup@food=Food.create!@measurement=@food.measurements.create!(:default=>true)enddeftest_find_does_not_stack_overflowFood.includes(:measurements).find(@food.id)enddeftest_where_does_not_stack_overflowFood.includes(:measurements).where(:id=>@food.id).firstenddeftest_find_by_does_not_stack_overflowFood.includes(:measurements).find_by(:id=>@food.id)enddeftest_find_by_id_does_not_stack_overflowFood.find_by_id(@food.id)enddeftest_find_by_id_with_joins_does_not_stack_overflowFood.joins(:measurements).find_by_id(@food.id)enddeftest_find_by_id_with_includes_does_not_stack_overflowbeginFood.includes(:measurements).find_by_id(@food.id)rescueSystemStackError=>eraise"find_by_id with includes produced a stack overflow"endenddeftest_find_by_id_with_joins_and_includes_does_not_stack_overflowbeginFood.joins(:measurements).includes(:measurements).find_by_id(@food.id)rescueSystemStackError=>eraise"find_by_id with includes and joins produced a stack overflow"endendend
This test fails with:
Finished in 1.063656s, 6.5811 runs/s, 0.0000 assertions/s.
1) Error:
BugTest#test_find_by_id_with_joins_and_includes_does_not_stack_overflow:
RuntimeError: find_by_id with includes and joins produced a stack overflow
wtfrails.rb:84:in `rescue in test_find_by_id_with_joins_and_includes_does_not_stack_overflow'
wtfrails.rb:81:in `test_find_by_id_with_joins_and_includes_does_not_stack_overflow'
2) Error:
BugTest#test_find_by_id_with_includes_does_not_stack_overflow:
RuntimeError: find_by_id with includes produced a stack overflow
wtfrails.rb:76:in `rescue in test_find_by_id_with_includes_does_not_stack_overflow'
wtfrails.rb:73:in `test_find_by_id_with_includes_does_not_stack_overflow'
7 runs, 0 assertions, 0 failures, 2 errors, 0 skips
Expected behavior
find_by_id, where(:id => id).first, find_by(:id => id) and find should all have the same callback behavior. They should not raise SystemStackError
Actual behavior
SystemStackError is raised.
System configuration
Rails version:
activerecord 5.1.0.alpha
activerecord 4.2.6
Ruby version:
ruby 2.3.1p112
The text was updated successfully, but these errors were encountered:
If a parent association was accessed in an `after_find` or
`after_initialize` callback, it would always end up loading the
association, and then immediately overwriting the association we just
loaded. If this occurred in a way that the parent's `current_scope` was
set to eager load the child, this would result in an infinite loop and
eventually overflow the stack.
For records that are created with `.new`, we have a mechanism to
perform an action before the callbacks are run. I've introduced the same
code path for records created with `instantiate`, and updated all code
which sets inverse instances on newly loaded associations to use this
block instead.
Fixesrails#26320.
Steps to reproduce
An executable test case is below. It demonstrates that
find_by_id
behaves differently thanfind(id)
,where(:id => id).first
, andfind_by(:id => id)
.find_by_id
is raising a SystemStackError when including has_many relationships and that relationship has an after_find callback that access the parent object.This test fails with:
Expected behavior
find_by_id, where(:id => id).first, find_by(:id => id)
and find should all have the same callback behavior. They should not raise SystemStackErrorActual behavior
SystemStackError is raised.
System configuration
Rails version:
Ruby version:
The text was updated successfully, but these errors were encountered: