Skip to content

Conversation

ndbroadbent
Copy link

@ndbroadbent ndbroadbent commented Sep 11, 2025

Motivation

This fixes a crash I was seeing with the Dotenv gem. They use ActiveSupport::Deprecation::DeprecatedConstantProxy for their old Railtie module so it blows up if anything touches it (since we raise on deprecation warnings in our app).

Implementation

I added some begin...rescue blocks to catch any deprecation exceptions and suppress them.

Tests

I've added some tests to ensure that tapioca ignores DeprecationException for these cases. These are the only locations where it was crashing, and now tapioca dsl runs without errors.

Crash Backtrace

/Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/compilers/active_support_concern.rb:76:in 'block in Tapioca::Dsl::Compilers::ActiveSupportConcern.gather_constants': DEPRECATION WARNING: Dotenv::Railtie is deprecated! Use Dotenv::Rails instead. (called from Kernel#load at ./bin/tapioca:27) (ActiveSupport::DeprecationException)
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/compilers/active_support_concern.rb:73:in 'Array#select'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/compilers/active_support_concern.rb:73:in 'Tapioca::Dsl::Compilers::ActiveSupportConcern.gather_constants'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'UnboundMethod#bind_call'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'block in Tapioca::Dsl::Compilers::ActiveSupportConcern._on_method_added'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/compiler.rb:46:in 'Tapioca::Dsl::Compiler.processable_constants'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/pipeline.rb:127:in 'block in Tapioca::Dsl::Pipeline#gather_constants'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/pipeline.rb:126:in 'Array#each'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/pipeline.rb:126:in 'Tapioca::Dsl::Pipeline#gather_constants'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'UnboundMethod#bind_call'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'block in Tapioca::Dsl::Pipeline#_on_method_added'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/dsl/pipeline.rb:53:in 'Tapioca::Dsl::Pipeline#run'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'UnboundMethod#bind_call'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'block in Tapioca::Dsl::Pipeline#_on_method_added'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/commands/abstract_dsl.rb:65:in 'Tapioca::Commands::AbstractDsl#generate_dsl_rbi_files'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/commands/dsl_generate.rb:17:in 'Tapioca::Commands::DslGenerate#execute'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'UnboundMethod#bind_call'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'block in Tapioca::Commands::DslGenerate#_on_method_added'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/commands/command.rb:28:in 'block in Tapioca::Commands::Command#run'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca.rb:20:in 'block in Tapioca.silence_warnings'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/site_ruby/3.4.0/rubygems/user_interaction.rb:46:in 'Gem::DefaultUserInteraction.use_ui'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca.rb:19:in 'Tapioca.silence_warnings'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/commands/command.rb:27:in 'Tapioca::Commands::Command#run'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'UnboundMethod#bind_call'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/sorbet-runtime-0.6.12466/lib/types/private/methods/_methods.rb:279:in 'block in Tapioca::Commands::Command#_on_method_added'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/lib/tapioca/cli.rb:179:in 'Tapioca::Cli#dsl'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/thor-1.4.0/lib/thor/command.rb:28:in 'Thor::Command#run'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/thor-1.4.0/lib/thor/invocation.rb:127:in 'Thor::Invocation#invoke_command'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/thor-1.4.0/lib/thor.rb:538:in 'Thor.dispatch'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/thor-1.4.0/lib/thor/base.rb:584:in 'Thor::Base::ClassMethods#start'
	from /Users/ndbroadbent/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/tapioca-0.17.7/exe/tapioca:31:in '<top (required)>'
	from ./bin/tapioca:27:in 'Kernel#load'
	from ./bin/tapioca:27:in '<main>'

@ndbroadbent ndbroadbent requested a review from a team as a code owner September 11, 2025 03:54
@ndbroadbent
Copy link
Author

I have signed the CLA!

!mod.singleton_class? &&
ActiveSupport::Concern > mod.singleton_class &&
has_dependencies?(mod)
rescue ActiveSupport::DeprecationException
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the right way to go 🙁 . Also, this could theoretically happen with any DSL compiler, and we'd need rescue calls in each one.

I took a look at alternatives, and unfortunately you can't use the --skip-constant option because those constants are still loaded during the gathering phase. I think the only other viable solutions are:

  1. Not loading the deprecated constant in the first place from your application. If it's not in ObjectSpace after app boot, it won't be accessed by Tapioca's DSL compilers.
  2. Don't raise deprecation warnings while Tapioca is running. You could detect this by looking at Kernel#caller or through an ENV variable set while running Tapioca.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this isn't the right fix.

We already have handling for DeprecatedConstantProxy classes in the gem pipeline, we could implement something similar in the DSL pipeline as well: https://github.com/Shopify/tapioca/blob/main/lib/tapioca/gem/pipeline.rb#L512-L524

@egiurleo egiurleo assigned egiurleo and unassigned egiurleo Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants