Ruslan Valeev
Ruslan Valeev

Reputation: 1907

Zeitwerk error on devise mailer in production environment

I have Rails 6, my preview class located in

mailer/previews/devise_mailer_preview.rb:

class DeviseMailerPreview < ActionMailer::Preview
  ...
end

And when I run application locally, everything is going fine, I can see my email previews on http://localhost:3000/rails/mailers/devise_mailer/confirmation_instructions address. But now Im trying to deploy application on server, and found that when I run bundle exec rails c production, I got the error:

/home/deploy/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/zeitwerk-2.3.0/lib/zeitwerk/loader/callbacks.rb:17:in `on_file_autoloaded': expected file /home/deploy/project/releases/20200627024908/app/mailer/previews/devise_mailer_preview.rb to define constant Previews::DeviseMailerPreview, but didn't (Zeitwerk::NameError)

After that I've checked locally RAILS_ENV=production rails c, and got same.

If I will rename DeviseMailerPreview class to Previews::DeviseMailerPreview, it will be broken and I cannot see emails on development, because Rails 6, accordingly to docs, expect exactly that name.

More of that, I've found in this article, that zeitwerk can be configured with autoload_paths param to avoid ruby's NameError. I found that I have it my config/application.rb:

config.load_defaults 6.0

Anyway I tried to add same row in my config/environments/production.rb file, but it didn't help.

What am I doing wrong and how can I fix it? Thanks in advance!

Upvotes: 2

Views: 2020

Answers (3)

Xavier Noria
Xavier Noria

Reputation: 2324

In Rails 6, previews are added to the autoload paths only if options.show_previews is true, which is not by default in the production environment. See the source code here.

The reason for this is that previews are supposed to be an aid for development, and they are generally not something you want to be able to look at in production.

However, you can set that flag to true in production if you want.

There's another derivative: By storing the previews under app/mailers, Rails is going to eager load them because app/mailers is in the autoload paths. If app/mailers/previews is not in the autoload paths, eager loading will fail due to the namespace mismatch. Either you have them enabled in all environments, or else is better to have them in a separate location, like the default.

Upvotes: 1

Quentin Gaultier
Quentin Gaultier

Reputation: 318

Add preview_path to the autoload_paths and zeitwerk will expect DeviseMailerPreview constant to be defined.

# development.rb

config.action_mailer.preview_path = Rails.root.join("app/mailers/previews")
# application.rb

config.autoload_paths << Rails.root.join("app/mailers/previews")

Upvotes: 1

cdadityang
cdadityang

Reputation: 543

Your Mailer preview file is located in mailer/previews/devise_mailer_preview.rb, so I'm assuming it's full path is app/mailer/previews/devise_mailer_preview.rb

The docs says

In the above example, the preview class for UserMailer should be named UserMailerPreview and located in test/mailers/previews/user_mailer_preview.rb

So put your devise_mailer_preview.rb file to test/mailers/previews/devise_mailer_preview.rb

or in your config/application.rb add this line and restart:

config.action_mailer.preview_path = "#{Rails.root}/app/mailers/previews"

Actually the answer was in the docs itself.

Upvotes: 0

Related Questions