view_component: GitHub Actions tests sometimes fail with the error "undefined local variable or method `call'" in a view component
Hello,
I’m using view_component in Avo quite a lot (about 95 components). Sometimes the tests fail when being run in GitHub Actions.
The error is ActionView::Template::Error: undefined local variable or method 'call' for #<Avo::PanelComponent:0x000055865888ba10>.
This error is never raised in my local environment.
Most times I hit “Re-run jobs” and the tests pass.
- The test in a PR made especially for this issue. Ruby 2.6, Rails 6.0
- Another test Ruby 2.6, Rails 6.0
- Another test Ruby 2.6, Rails 6.1
- The actual PR.
It seems it only happens for PanelComponent.
PanelComponentsource codeResourceIndexComponentthe place where the error is raised.
Steps to reproduce
I can’t reproduce it locally. It only happened on GA and sporadically.
Expected behavior
The tests should pass without raising this error.
Actual behavior
Raises this error sporadically. It’s not raised every time.
System configuration
Rails version: Tested with 6.0 and 6.1
Ruby version: Tested with 2.6 and 2.7
Gem version: view_component (2.28.0)
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 44 (26 by maintainers)
In some CI runs on my PR, before I’ve finalised the code, I’ve managed to obtain the undefined method
callerror.After adding the Mutex, I’ve solved that error but I started getting a deadlock error. After replacing the mutex with a monitor, the error was fixed.
I’ve also added a new test, which concurrently renders a component 100 times starting from a cleared cache. Before adding my code, that test was failing, now it is passing.
I have a sample app where I can reproduce this on a production env here
The issue comes from view_component_storybook, and our configuration where we set
app/componentsas the storybook_path. We set it like this:Rails.application.config.view_component_storybook.stories_path = Rails.root.join("app/components")which generates a pathname object:#<Pathname:/#{path_to_app}/cometeer/app/components>.However, Rails adds
app/componentsto eager and auto load as a string and not a Pathname object. (I’m assuming this functionality is coming from Rails, anyway).So the order of operations is:
app/componentsto eager and autoload.app/componentsto autoloadapp/componentsis not the same as stringapp/components, and so in the setup_autoloaders method of ActiveSupport,app/componentsis not recognized as eager_loaded, and is specifically removed from eager_loadingapp/componentsget loaded past this point ¯_(ツ)_/¯For us, the solution is simple: add a
to_stoRails.root.join("app/components"). I’ll open an issue on view_component_storybooks too, though.@seand7565 , Yes, actually… We do not get any issue on specs, but sometimes on production. So i’m going to try this fix… We are hosted on Heroku, and spend sometime researching but cant reproduce on development or local.
That did the trick! Thank you indeed.
(I think ripping it all out was completely genius 🚀)
This should be fixed in v2.74.1. Please reopen if not ❤️
This (ugly) workaround fixed the issue in production for us:
Seems plausible at this point that two (or more) threads are trying to compile at the same time, and the
sleephelps passing control to the original thread so that it’s able to finish.The sequence could be something like:
compiled?isfalse, starts compilationcompiled?isfalse, starts compilation (while thread1 is still compiling)compiled?is now true and starts rendering componentscallin order to redefine itNameError: undefined method callcompiled?as true@adrianthedev you know if the failing specs you’re getting are using puma with multiple threads?