Skip to content

Commit

Permalink
Fix ActiveRecordFixtures compiler for Rails 7+
Browse files Browse the repository at this point in the history
Fixtures no longer eagerly define methods, but instead rely on
`method_missing` to handle fixture methods lazily. Thus, the
implementation needs to change to lookup fixture names in the new
`fixture_sets` class attribute.

Upstream PR: rails/rails#44528
  • Loading branch information
paracycle committed Aug 10, 2022
1 parent 236bf78 commit 8f43438
Showing 1 changed file with 24 additions and 9 deletions.
33 changes: 24 additions & 9 deletions lib/tapioca/dsl/compilers/active_record_fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ class ActiveRecordFixtures < Compiler

sig { override.void }
def decorate
method_names = fixture_loader.ancestors # get all ancestors from class that includes AR fixtures
.drop(1) # drop the anonymous class itself from the array
.reject(&:name) # only collect anonymous ancestors because fixture methods are always on an anonymous module
.map! do |mod|
[mod.private_instance_methods(false), mod.instance_methods(false)]
end
.flatten # merge methods into a single list
method_names = if fixture_loader.respond_to?(:fixture_sets)
method_names_from_lazy_fixture_loader
else
method_names_from_eager_fixture_loader
end

return if method_names.empty?

root.create_path(constant) do |mod|
Expand All @@ -69,11 +68,27 @@ def self.gather_constants

sig { returns(Class) }
def fixture_loader
Class.new do
@fixture_loader ||= T.let(Class.new do
T.unsafe(self).include(ActiveRecord::TestFixtures)
T.unsafe(self).fixture_path = Rails.root.join("test", "fixtures")
T.unsafe(self).fixtures(:all)
end
end, T.nilable(Class))
end

sig { returns(T::Array[String]) }
def method_names_from_lazy_fixture_loader
T.unsafe(fixture_loader).fixture_sets.keys
end

sig { returns(T::Array[Symbol]) }
def method_names_from_eager_fixture_loader
fixture_loader.ancestors # get all ancestors from class that includes AR fixtures
.drop(1) # drop the anonymous class itself from the array
.reject(&:name) # only collect anonymous ancestors because fixture methods are always on an anonymous module
.map! do |mod|
[mod.private_instance_methods(false), mod.instance_methods(false)]
end
.flatten # merge methods into a single list
end

sig { params(mod: RBI::Scope, name: String).void }
Expand Down

0 comments on commit 8f43438

Please sign in to comment.