Zeitwerk error with ViewComponents in production

I’m building a Rails app, with search powered by Ransack. I’m using ViewComponents for most of my UI.

ViewComponents by design do not have access to most Rails view helpers, including Ransack’s search_form_for helper. To make it work, I included the relevant Ransack helper directly into my component, like so:

class SearchBox::SearchBoxComponent < BaseComponent
  include Ransack::Helpers::FormHelper
end

It works great in development. But in prod, the server won’t start.

I get the following Zeitwerk error:

uninitialized constant Ransack::Helpers (NameError)

  include Ransack::Helpers::FormHelper
                          ^^^^^^^^^^^^

Zeitwerk is trying to eager load all the app files and is getting stuck on this include for some reason.

I’ve tried adding require 'ransack' at the start of the file but no luck.

What can I do to fix this?

Turns out I needed to require the exact file path:

require 'ransack/helpers/form_helper'

class SearchBox::SearchBoxComponent < BaseComponent
  include Ransack::Helpers::FormHelper
end
1 Like

That seems to be correct.

From what I see, Ransack is a regular Ruby gem that does not have autoload in place. Therefore, you use it as with any other gem, issuing require calls for what you need. According to their source code, you need just

require 'ransack/helpers'

Note the on_load callback configured by the gem. That may explain why it works in development, and not in production. Because in development mode you reach that constant once the block has been executed, but in production mode (a posteriori), that block did not get a chance.

That is why we recommend to eager load in CI:

# config/environments/test.rb
config.eager_load = ENV['CI'].present?

because any possible gotcha happening during eager loading is going to be detected there first.

3 Likes