strict_loading_by_default was added to ActiveRecord 6.1. How can we eager load fixture associations to make tests pass once this flag is used?
class ApplicationRecord < ActiveRecord::Base
self.strict_loading_by_default = true
end
# app/models/post.rb
class Post < ApplicationRecord
belongs_to :author
end
# app/models/author.rb
class Author < ApplicationRecord; end
# test/fixtures/posts.yml
my_post:
author: my_author
# test/fixtures/authors.yml
my_author: {}
# test/models/post_test.rb
class PostTest < ActiveSupport::TestCase
test "post belongs to author" do
post = posts(:my_post)
assert post.author # Minitest::UnexpectedError: ActiveRecord::StrictLoadingViolationError:
# `Author` called on `Post` is marked for strict_loading and cannot be lazily loaded.
end
end
I gave another try to this strict_loading feature, both using self.strict_loading_by_default = true on the model and by passing .strict_loading to the association. However because of the new fix described in this thread, the actual N+1 query problems donât get caught in tests and thus the parity between test and prod is lost (no exceptions are raised in tests even when executing code with N+1 queries, but exceptions are raised once running the same code in prod).
Therefore, what is the proper/official way to do non-regression testing of associations which are strictly loaded? Is this documented somewhere? Is there any way to restore the functionality even when using fixtures, or does it mean we cannot use fixtures any more? Should the tests be rewritten? What is the new alternative?
@ghiculescu or others, any advice? Any insight would be very much appreciated, thanks
OK it seems that my problems are not about fixtures (thanks @ghiculescu for the guidance in the GitHub issue), however I didnât manage to enforce strict loading in this example, any ideas?
If you eager load an association with a specified :limit option, it will be ignored, returning all the associated objects:
class Picture < ActiveRecord::Base
has_many :most_recent_comments, -> { order('id DESC').limit(10) }, class_name: 'Comment'
end
Picture.includes(:most_recent_comments).first.most_recent_comments # => returns all associated comments.
Eager loading is supported with polymorphic associations.
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
end
A call that tries to eager load the addressable model
Address.includes(:addressable)
This will execute one query to load the addresses and load the addressables with one query per addressable type. For example, if all the addressables are either of class Person or Company, then a total of 3 queries will be executed. The list of addressable types to load is determined on the back of the addresses loaded.
Did you have a fix on this issue? I have the same problem with Facing same issue but no response from anyone and couldnt find this topic troubleshooting in google.
@Lexingtonn the specific issue I had (there might be others) was that find_by doesnât care about eager loading. A fix was proposed by Alex in the thread I linked: