I am back again with my ctrlpanel application.
I have it 100% working in development and went through the process to get it loaded up to Heroku and got the app up, gems installed. DB is there (mostly) but I have an issue even before the DB. I am getting an error dealing with devise_invitable that I DO NOT get in Development. To my surprise I do get the same error when I launch production on my laptop which was shocking to me to say the least as everything works perfect in development. So I know it isn't a Heroku issue which I am happy about at least I can reproduce it. The full error is below here but the line that specifically deals with the error is:
"C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader/callbacks.rb:18:in `on_file_autoloaded': expected file D:/rails/ctrlpanel/app/controllers/invitations_controller.rb to define constant InvitationsController, but didn't (Zeitwerk::NameError)C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader/callbacks.rb:18:in `on_file_autoloaded': expected file D:/rails/ctrlpanel/app/controllers/invitations_controller.rb to define constant InvitationsController, but didn't (Zeitwerk::NameError)"
I did some searching online (a lot of it actually) and the only thing I could find was a recommendation to copy the invitations_controller.rb file into a folder called users under the controllers folder, which I did try, I made a copy of it actually and I did also try moving it. Neither of which helped. This works properly in development. SO I started comparing the 2 environment files.
I got past it by changing these 2 entries:
config.cache_classes = false in production.rb
config.eager_load = false in production.rb
However I have seen postings everyplace that turning those 2 options off is very bad and it will effect the views somehow and sure enough my bootstrap is all caddywhompused which I can only assume is due to those 2 options being off. I'm sure someone else must have seen this before but I can't seem to find anything. I checked the devise_invitable docs, updated it to a v .02 higher (no effect).
The error is so long I am having a hard time find a good search term to get results.
I am confused as everything must be correct or it wouldn't be working right in development or I wouldn't think so? If there is any other file that needs to be seen please let me know and I will be happy to display it.
Thank you in advance for any help or advice you can offer.
Scott
Here is the error:
scottm@RED-IT-LAP-0001 MINGW64 /d/rails/ctrlpanel (master)
$ rails server -e production
=> Booting Puma
=> Rails 6.1.3.2 application starting in production
=> Run `bin/rails server --help` for more startup options
Exiting
Traceback (most recent call last):
67: from bin/rails:14:in `<main>'
66: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
65: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
64: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
63: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
62: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
61: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/commands.rb:18:in `<main>'
60: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/command.rb:50:in `invoke'
59: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/command/base.rb:69:in `perform'
58: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch'
57: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command'
56: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/thor-1.1.0/lib/thor/command.rb:27:in `run'
55: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/commands/server/server_command.rb:135:in `perform'
54: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/commands/server/server_command.rb:135:in `tap'
53: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/commands/server/server_command.rb:144:in `block in perform'
52: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/commands/server/server_command.rb:39:in `start'
51: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/server.rb:311:in `start'
50: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/server.rb:379:in `handle_profiling'
49: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/server.rb:312:in `block in start'
48: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/server.rb:422:in `wrapped_app'
47: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/server.rb:249:in `app'
46: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/server.rb:349:in `build_app_and_options_from_config'
45: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:66:in `parse_file'
44: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:105:in `load_file'
43: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:116:in `new_from_string'
42: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:116:in `eval'
41: from config.ru:3:in `block in <main>'
40: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.1.3.2/lib/active_support/dependencies.rb:332:in `require'
39: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.1.3.2/lib/active_support/dependencies.rb:299:in `load_dependency'
38: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/activesupport-6.1.3.2/lib/active_support/dependencies.rb:332:in `block in require'
37: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:34:in `require'
36: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
35: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
34: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
33: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
32: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bootsnap-1.7.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
31: from D:/rails/ctrlpanel/config/environment.rb:5:in `<main>'
30: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/railtie.rb:207:in `method_missing'
29: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/railtie.rb:207:in `public_send'
28: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/application.rb:384:in `initialize!'
27: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:60:in `run_initializers'
26: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:205:in `tsort_each'
25: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:226:in `tsort_each'
24: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:347:in `each_strongly_connected_component'
23: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:347:in `call'
22: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:347:in `each'
21: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:349:in `block in each_strongly_connected_component'
20: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:431:in `each_strongly_connected_component_from'
19: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
18: from C:/Ruby27-x64/lib/ruby/2.7.0/tsort.rb:228:in `block in tsort_each'
17: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:61:in `block in run_initializers'
16: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:32:in `run'
15: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/initializable.rb:32:in `instance_exec'
14: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/railties-6.1.3.2/lib/rails/application/finisher.rb:133:in `block in <module:Finisher>'
13: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:508:in `eager_load_all'
12: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:508:in `each'
11: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:393:in `eager_load'
10: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:393:in `synchronize'
9: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:404:in `block in eager_load'
8: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:725:in `ls'
7: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:725:in `foreach'
6: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:733:in `block in ls'
5: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:409:in `block (2 levels) in eager_load'
4: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:409:in `const_get'
3: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:26:in `require'
2: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:26:in `tap'
1: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:27:in `block in require'
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader/callbacks.rb:18:in `on_file_autoloaded': expected file D:/rails/ctrlpanel/app/controllers/invitations_controller.rb to define constant InvitationsController, but didn't (Zeitwerk::NameError)
Here is the routes.rb file:
Catalog::Application.routes.draw do
resources :redline_filters
resources :certifications
resources :routes do
resources :waypoints, only: [:show, :destroy]
end
resources :dealerships do
collection do
get 'index_public'
get 'deduplicate'
end
resources :visits
end
resources :items do
resources :variants, except: :index do
resources :snapshots
end
end
resources :crosses do
collection do
get 'index_public'
end
end
root to: 'static_pages#home'
devise_for :users, controllers: { invitations: 'users/invitations' }
resources :locations, :categories, :gfe_users, :trips, :vendors, :work_orders
resources :attachments, only: [:destroy]
get '/gfe_reporting', to: 'gfe_users#reporting'
resources :users do
get 'toggle_suspend'
end
resources :charges do
collection do
post 'import'
end
end
resources :products do
match 'submit' => 'products#submit', via: [:get, :post]
match 'publish' => 'products#publish', via: [:get, :post]
match 'in_progress' => 'products#in_progress', via: [:get, :post]
# collection { post :search, to: 'products#index' } ## ransack crap.
end
resources :devices do
resources :trips
end
# match "/home" => 'static_pages#home'
match "/catalog" => 'static_pages#catalog', via: [:get, :post]
match "product/:name" => "products#index", via: [:get, :post]
get "static_pages/products"
get "static_pages/catalog"
get "static_pages/help"
get "static_pages/roi"
get "/roi", to: "static_pages#roi"
match 'device_lookup', to: 'devices#lookup', via: [:get, :post]
match 'device_first_avaiable_serial', to: 'devices#first_available_serial', via: [:get, :post]
match 'device_battery_is_dead' => 'devices#update_status_to_dead_battery', via: [:get, :post]
match 'device_is_missing' => 'devices#is_missing', via: [:get, :post]
match 'device_has_water_damage' => 'devices#update_status_to_water_damage', via: [:get, :post]
match 'device_is_rma' => 'devices#update_status_to_rma', via: [:get, :post]
match 'device_is_healthy' => 'devices#is_healthy', via: [:get, :post]
match 'pending_trip' => 'trips#pending_trip', via: [:get, :post]
match 'complete_trip' => 'trips#complete_trip', via: [:get, :post]
# The priority is based upon order of creation:
# first created -> highest priority.
# Sample of regular route:
# match 'products/:id' => 'catalog#view'
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
# This route can be invoked with purchase_url(:id => product.id)
# Sample resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Sample resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Sample resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Sample resource route with more complex sub-resources
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', :on => :collection
# end
# end
# Sample resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
# root :to => 'welcome#index'
# See how all your routes lay out with "rake routes"
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
# match ':controller(/:action(/:id))(.:format)'
end
Here is the invitations_controller.rb file:
class User::InvitationsController < Devise::InvitationsController
def new
if cannot?(:invite, User)
raise CanCan::AccessDenied
else
super
end
end
def create
if cannot?(:invite, User)
raise CanCan::AccessDenied
else
self.resource = resource_class.invite!(resource_params, current_inviter)
unless resource.role.present?
resource.role = "creator"
resource.save
end
if resource.errors.empty?
set_flash_message :notice, :send_instructions, :email => self.resource.email
respond_with resource, :location => after_invite_path_for(resource)
else
respond_with_navigational(resource) { render :new }
end
end
end
private
def resource_params
params.permit(user: [:name, :email, :invitation_token, :location_id])[:user]
end
end
Here is the application_controller.rb file:
class ApplicationController < ActionController::Base
protect_from_forgery prepend: true
#before_filter :configure_permitted_parameters, if: :devise_controller?
before_action :configure_permitted_parameters, if: :devise_controller?
#before_filter :authenticate_user!
before_action :authenticate_user!
#check_authorization :unless => :devise_controller?
after_action :unless => :devise_controller?
before_action :set_paper_trail_whodunnit
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [ :first_name, :last_name, :email] )
devise_parameter_sanitizer.permit(:account_update, keys: [ :first_name, :last_name, :phone, :email ] )
devise_parameter_sanitizer.permit(:invite, keys: [ :name, :location_id ] )
end
end
Just in case here is also the application.rb file
require_relative "boot"
require "rails/all"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Catalog #Ctrlpanel
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
config.before_configuration do
env_file = File.join(Rails.root, 'config', 'local_env.yml')
YAML.load(File.open(env_file)).each do |key, value|
ENV[key.to_s] = value
end if File.exists?(env_file)
end
config.autoload_paths += %W(#{config.root}/lib)
config.encoding = "utf-8"
config.time_zone = 'Pacific Time (US & Canada)'
config.active_record.default_timezone = :local
config.filter_parameters += [:password]
config.active_support.escape_html_entities_in_json = true
# Enable pdf.css precompiling for wicked_pdf
config.assets.precompile += %w( pdf.css print.css awesome-bootstrap-checkbox.css jquery.dataTables.min.css )
# Force Heroku to not access the DB or load models when precompiling your assets.
config.assets.initialize_on_precompile = false
# Use SQL instead of Active Record's schema dumper when creating the database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Enforce whitelist mode for mass assignment.
# This will create an empty whitelist of attributes available for mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
# This breaks the application 3/30/2021 Scott Milella
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
# in config/environments, which are processed later.
#
# config.time_zone = "Central Time (US & Canada)"
# config.eager_load_paths << Rails.root.join("extras")
# No Method Error message 3/31/2021 Scott Milella
#config.active_record.raise_in_transactional_callbacks = true
end
end
I figured it out this morning.
I learned about a command called: rails zeitwerk:check --trace
When I ran it, it gave me this specific error: Hold on, I am eager loading the application. expected file app/controllers/users/invitations_controller.rb to define constant Users::InvitationsController
When I looked at my user model the main class declaration was written as: class User::InvitationsController < Devise::InvitationsController
The name of the model is user.rb so based on my experience with other languages I assumed the class name and the model name had to match, but I tried to rename it to:
class Users::InvitationsController < Devise::InvitationsController
I added the s in the Users::InvitationsController and then I ran the zeitwerk:check --trace again and it passed, I then tried to load the application into Production and what do you know it worked?
SO the SOLUTION in my case was in 2 parts:
1 Thank you @Scott Matthewman who informed me I needed to in fact MOVE the invitations_contoller.rb into a folder under controllers called users
/app/controllers/users.
2 I had to rename the User to Users in the class declaration (if that is the term in Ruby/Rails).
FROM:
User::InvitationsController < Devise::InvitationsController
TO:
Users::InvitationsController < Devise::InvitationsController