From 2be6bbb0ac693e991824df9c6e12229d43d26899 Mon Sep 17 00:00:00 2001 From: Ufuk Kayserilioglu Date: Thu, 11 Jul 2024 23:38:54 +0300 Subject: [PATCH] Short circuit Rails app loading if Rails constant isn't defined There are sometimes Rails-lookalike applications that might have defined a `config/application.rb` file but don't actually have Rails loaded. This change short circuits the Rails app loading if the `Rails` constant isn't defined after loading the `config/environment.rb` file or the `config/application.rb` file. --- lib/tapioca/loaders/loader.rb | 19 ++++++++++--- spec/tapioca/cli/dsl_spec.rb | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/lib/tapioca/loaders/loader.rb b/lib/tapioca/loaders/loader.rb index 2dfeebd07..0e1aeff4d 100644 --- a/lib/tapioca/loaders/loader.rb +++ b/lib/tapioca/loaders/loader.rb @@ -47,12 +47,23 @@ def load_bundle(gemfile, initialize_file, require_file, halt_upon_load_error) ).void end def load_rails_application(environment_load: false, eager_load: false, app_root: ".", halt_upon_load_error: true) - return unless File.exist?("#{app_root}/config/application.rb") + return unless File.exist?(File.expand_path("config/application.rb", app_root)) - if environment_load - require "./#{app_root}/config/environment" + load_path = if environment_load + "config/environment" else - require "./#{app_root}/config/application" + "config/application" + end + + require File.expand_path(load_path, app_root) + + unless defined?(Rails) + say( + "\nTried to load the app from `#{load_path}` as a Rails application " \ + "but the `Rails` constant wasn't defined after loading the file.", + :yellow, + ) + return end eager_load_rails_app if eager_load diff --git a/spec/tapioca/cli/dsl_spec.rb b/spec/tapioca/cli/dsl_spec.rb index b421f194b..55921b07e 100644 --- a/spec/tapioca/cli/dsl_spec.rb +++ b/spec/tapioca/cli/dsl_spec.rb @@ -2801,6 +2801,56 @@ class PostCompiler < Tapioca::Dsl::Compiler end end + describe "rails-like-applications" do + before(:all) do + @project.write!("config/environment.rb", <<~RB) + require_relative "application.rb" + RB + + @project.write!("config/application.rb", <<~RB) + # Don't define any constant named `Rails`. + require "smart_properties" + + class Post + include SmartProperties + property :title, accepts: String + end + RB + + @project.require_real_gem("smart_properties", "1.15.0") + @project.bundle_install! + end + + after(:all) do + @project.remove!("config/application.rb") + end + + it "shows a warning about the Rails constant not having been loaded" do + res = @project.tapioca("dsl") + + assert_stdout_equals(<<~OUT, res) + Loading DSL extension classes... Done + Loading Rails application...\u0020 + Tried to load the app from `config/environment` as a Rails application but the `Rails` constant wasn't defined after loading the file. + Done + Loading DSL compiler classes... Done + Compiling DSL RBI files... + + create sorbet/rbi/dsl/post.rbi + + Done + + Checking generated RBI files... Done + No errors found + + All operations performed in working directory. + Please review changes and commit them. + OUT + assert_empty_stderr(res) + assert_success_status(res) + end + end + describe "halt-upon-load-error" do before(:all) do @project.write!("config/environment.rb", <<~RB)