-
Notifications
You must be signed in to change notification settings - Fork 156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Rails app detection based on Rails::Application superclass #2218
Conversation
This looks nice, thanks for picking this up! I've closed my PR since it missed the mark somewhat. I tried giving this a shot but testing this out proved a bit more complicated. One issue I'm certain of is that a
Can't use |
Interesting, I'm surprised that no tests fail because of this (at least locally). Maybe because the tests already require Prism somewhere? |
The test helper has |
17a19de
to
2d5c93f
Compare
732be3a
to
ccdb0a6
Compare
The changes look good, but there's a test failing. |
@vinistock As I said in the original description, the tests all pass in isolation, but fail when ran together. I was not able to pinpoint the context leak between the tests. I will take another look, but if you have an idea on top of your head, as I'm not very familiar with Minitest so I might have overlooked something obvious. |
I'm looking into. It can be reproduced consistently with this seed:
|
The minimal set of tests that causes this are:
|
If I check
🤔 |
This looks like a bundler caching thing, I ran into something similar over at RuboCop a bit ago. I added this helper to fully isolate bundler (at least as far as was relevant): https://github.com/rubocop/rubocop/blob/66435058ed2310b509febc88f689f4a7e04e9e9e/lib/rubocop/rspec/shared_contexts.rb#L55-L72 If you wrap |
@Earlopain thanks for the pointer. I've pushed a commit on a different branch, and it's passing: Will need to discuss with @vinistock if there is a better way to handle. |
Spoke too soon, there might be something else that needs wrapped in |
This change makes the Rails app detection based on the superclass of the main class being `Rails::Application`. This is a more reliable way to detect Rails apps than looking for the presence of the `rails` gem in the Gemfile. Application can require some of the Rails components without requiring the `rails` gem itself. co-authored-by: Earlopain <14981592+Earlopain@users.noreply.github.com>
ccdb0a6
to
41d69b5
Compare
I tried investigating the test failure again but didn't make any progress. How about just changing the code a bit to not run into that problem? I tested out the following patch locally and it doesn't appear to fail: diff --git a/lib/ruby_lsp/setup_bundler.rb b/lib/ruby_lsp/setup_bundler.rb
index 903f43a3..b3ef164b 100644
--- a/lib/ruby_lsp/setup_bundler.rb
+++ b/lib/ruby_lsp/setup_bundler.rb
@@ -285,11 +285,15 @@ module RubyLsp
# Detects if the project is a Rails app by looking if the superclass of the main class is `Rails::Application`
sig { returns(T::Boolean) }
def rails_app?
- config = Pathname.new("config/application.rb").expand_path
- application_contents = config.read if config.exist?
- return false unless application_contents
+ return false unless (application_contents = rails_application_content)
/class .* < Rails::Application/.match?(application_contents)
end
+
+ sig { returns(T.nilable(String)) }
+ def rails_application_content
+ config = Pathname.new("config/application.rb").expand_path
+ config.read if config.exist?
+ end
end
end
diff --git a/test/setup_bundler_test.rb b/test/setup_bundler_test.rb
index 77f3b605..a65d7b3c 100644
--- a/test/setup_bundler_test.rb
+++ b/test/setup_bundler_test.rb
@@ -75,33 +75,33 @@ class SetupBundlerTest < Minitest::Test
end
def test_creates_custom_bundle_for_a_rails_app
- Dir.mktmpdir do |dir|
- Dir.chdir(dir) do
- FileUtils.mkdir(File.join(dir, "config"))
- File.write(File.join(dir, "config", "application.rb"), <<~RUBY)
- module MyApp
- class Application < Rails::Application
- end
- end
- RUBY
-
- Object.any_instance.expects(:system).with(
- bundle_env(".ruby-lsp/Gemfile"),
- "(bundle check || bundle install) 1>&2",
- ).returns(true)
- Bundler::LockfileParser.any_instance.expects(:dependencies).returns({ "rails" => true }).at_least_once
- run_script
+ Object.any_instance.expects(:system).with(
+ bundle_env(".ruby-lsp/Gemfile"),
+ "(bundle check || bundle install) 1>&2",
+ ).returns(true)
- assert_path_exists(".ruby-lsp")
- assert_path_exists(".ruby-lsp/Gemfile")
- assert_path_exists(".ruby-lsp/Gemfile.lock")
- assert_path_exists(".ruby-lsp/main_lockfile_hash")
- gemfile_content = File.read(".ruby-lsp/Gemfile")
- assert_match("ruby-lsp", gemfile_content)
- assert_match("debug", gemfile_content)
- assert_match("ruby-lsp-rails", gemfile_content)
+ # There is some unknown state leak with Bundler which prevents us from creating the
+ # folder structure ourselves lest we encounter flaky tests
+ RubyLsp::SetupBundler.any_instance.stubs(:rails_application_content).returns(<<~RUBY)
+ module MyApp
+ class Application < Rails::Application
+ end
end
- end
+ RUBY
+
+ Bundler::LockfileParser.any_instance.expects(:dependencies).returns({ "rails" => true }).at_least_once
+
+ run_script
+
+ assert_path_exists(".ruby-lsp")
+ assert_path_exists(".ruby-lsp/Gemfile")
+ assert_path_exists(".ruby-lsp/Gemfile.lock")
+ assert_path_exists(".ruby-lsp/main_lockfile_hash")
+ assert_match("ruby-lsp", File.read(".ruby-lsp/Gemfile"))
+ assert_match("debug", File.read(".ruby-lsp/Gemfile"))
+ assert_match("ruby-lsp-rails", File.read(".ruby-lsp/Gemfile"))
+ ensure
+ FileUtils.rm_r(".ruby-lsp") if Dir.exist?(".ruby-lsp")
end
def test_changing_lockfile_causes_custom_bundle_to_be_rebuilt |
a20372d
to
7de9b47
Compare
7de9b47
to
f403aeb
Compare
@Earlopain I've taken your suggestion but made a slight change so that we use a file fixture instead of needing to stub the private method (which may be brittle). |
Co-authored-by: Alexandre Terrasa <583144+Morriar@users.noreply.github.com>
Any further thoughts @vinistock @st0012 ? |
efd2780
to
89349a3
Compare
89349a3
to
8dc23d1
Compare
Hmm, as per @vinistock's comment here, should we remove the |
I think that is fine to leave as is, the rails plugin uses |
Hey! This looks like it's ready to merge. It would be nice to have this in. |
Co-authored-by: Vinicius Stock <vinistock@users.noreply.github.com>
Seems there is an issue when the file contains non-ASCII characters: #2463 |
Motivation
closes #2096
This change makes the Rails app detection based on the superclass of the main class being
Rails::Application
. This is a more reliable way to detect Rails apps than looking for the presence of therails
gem in the Gemfile. Application can require some of the Rails components without requiring therails
gem itself.Implementation
The implementation is strongly inspired from #2161, hat tip to @Earlopain. I've added you as a co-author; let me know if that's ok.
Automated Tests
The test all pass individually. However, when the full file is executed, one of the test doesn't pass. It's most certainly related to something I have changed. I wasn't able to pinpoint if context is leaking between tests or if something else is happening. Since this is also my first time using minitest, an experienced eye would be appreciated.
The problem can be reproduced with:
Relevant snip in case it doesn't fail:
Manual Tests
I haven't yet tested in our app, will do so as soon as possible.