I have a rails app in development mode.
When I make changes to a ruby class called 'Dummy' under lib/dummy it doesn't get automatically reloaded, until I restart the rails server.
The class lives in a file under
lib/dummy/dummy.rb
class Dummy
def test
puts "XXX #{var_that_does_not_exist.stuff} XXX"
end
end
If I run this, the controller that calls
dummy = Dummy.new
dummy.test
causes an error as the variable 'var_that_does_not_exist' doesn't exist. If I updated the code to remove that variable, and make another request it continues to fail, until I actually restart the rails server.
development.rb contains
config.cache_classes = false
config.reload_classes_only_on_change = false
config.serve_static_assets = false
application.rb contains
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]
config.autoload_paths += Dir["#{config.root}/lib/duummy/"]
Related
I have a problem because my code does not work on the production server. When it comes to development environment, everything is fine. It looks like he doesn't read the classes. My ruby version is 2.6.6 and rails is set as 5.2.4.4.
lib/crm/api.rb
module CRM
class API
# some code
end
end
app/services/crm/changes.rb
module CRM
class Changes
def initialize
#api = API.new
end
# some code
end
end
The main service is running as a cronjob.
config/schedule.rb
every 5.minutes do
runner('CRM::CheckChanges.new.call', output: "#{path}/log/crm_check_changes.log")
end
And run this code
app/services/crm/check_changes.rb
module CRM
class CheckChanges
def initialize
#changes = Changes.new
end
# some code
end
end
At first I got errors log like 'Uninitialized constant CRM::Changes::API' after reload background jobs I got 'Unitialized constant CRM::API'
config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += %W(#{config.root}/app)
Dir.glob(Rails.root.join('lib/**')).inject(config.autoload_paths){ |autoload_paths, path| autoload_paths << path }
As I mentioned before everything works fine on development environment. Does anyone have any idea what this could be about? Thanks in advance for answer.
You need to add /lib to the eager load paths as well:
config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
The default setting for production uses eager loading (all the classes are loaded at startup) instead of autoloading.
In production, however, you want consistency and thread-safety and can
live with a longer boot time. So eager_load is set to true, and then
during boot (before the app is ready to receive requests) Rails loads
all files in the eager_load_paths and then turns off auto loading (NB:
autoloading may be needed during eager loading). Not autoloading after
boot is a good thing, as autoloading can cause the app to have
thread-safety problems.
See Autoloading and Reloading Constants (Classic Mode). Also note that /app and all its subdirecties are already on the autoloading paths.
I'd like to add a microapp for errors to be processed (file I placed inside the lib folder).
module MyApp
class Application < Rails::Application
config.autoload_paths += %W( #{config.root}/lib )
config.exceptions_app = FooApp.new(Rails.public_path)
end
end
But Rails raises an unitialized constant (NameError) during it's initialization. Recently I found a similar post and tried every solution from there, but got no result. What actually I've tried:
Name a class and a filename according to convention (even tried to simplify to a single word - class Foo, filename lib/foo.rb).
Use config.eager_load_paths += %W( #{config.root}/lib ) rather than config.autoload_paths, same effect. :(
Create an initializer file and load a class with require: require "#{Rails.root}/lib/foo"
It doesn't work - seems initializers are performed after the initial Rails configuration.
Move the file into app/misc but it doesn't help.
Put a class inside a module with the same name, rename a class while it's still in the module - no effect.
The only working solution I found - is to require a file right inside the Rails configuration block, but... it's a freaky solution. Probably there still exists an idiomatic one?
I noticed that my configuration which was parsed from a yml file is not being reloaded when I start up a console. Here is my application.rb file:
module MyApp
def self.config
Rails.application.config.yml_data['common']
end
class Application < Rails::Application
config.yml_data = YAML.load(ERB.new(File.read(Rails.root.join('config', 'platform', 'config.yml'))).result)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
end
end
I have config.cache_classes set to false. Is there a way to reload MyApp ??? The config never gets updated.
If you change things while the rails console is opened it will not automatically reload them. You have to use the command reload!
If it wasn’t what you are trying to do, please explain it with more detail.
Try adding your config file path to config.autoload_paths like its said on documentation
Title says it all.
Note that this is not about a change in the model or initializers.
I can delete an instance variable in the controller (say, #user) and then reload a view and it will work - until I restart the server, in which case it will complain about the variable being nil.
I was working normally and then switched to work on a totally different set of controllers and views and now it's happening for no reason whatsoever.
The app is in a development environment.
development.rb contents:
Dashboard::Application.configure do
config.cache_classes = false
config.whiny_nils = true
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_mailer.raise_delivery_errors = false
config.active_support.deprecation = :log
config.action_dispatch.best_standards_support = :builtin
config.assets.compress = false
config.assets.debug = true
end
How can I find out how it's happening and how do I fix it?
Edit:
**It's likely related, but I can't seem to use any paths that exist when running 'rake routes' in a partial, such as dashboards_path**
Plot twist:
Adding
config.reload_classes_only_on_change = false
to development.rb seemed to have ameliorated the issue. I still would like to know why it happened, why it happened out of the blue and why it happened to one controller but not the other.
Rails uses the autoload paths config to determine what files to auto load, and reload:
module YourApp
class Application < Rails::Application
config.autoload_paths += %W( #{config.root}/lib #{config.root}/lib/**/ #{config.root}/app/traits )
...
end
end
As you can see I have added a custom directory, the app/traits directory, where I store some modules that define shared behavior.
If the controller you started working on is in a subdirectory that is not watched by rails or has permissions that stop rails from attaching a file system changed event you get this problem.
The reason that config.reload_classes_only_on_change = false "solves" the problem is that the entire app is reloaded on every request instead of relying on detecting changes to files.
Most likely the controller is not in the watched files list and thats why rails is not reloading it on change. The exact reason why it's not on the list might vary and I need more details about the folder structure and config of the app before I can give a good answer there...
I have a rails application that patches ActiveRecord with a hand-coded validator.
The patch is made by adding the following lines in config/environment.rb
Rails::Initializer.run do |config|
...
end
class ActiveRecord::Base
include MtLib::DBValidations
end
This works fine in production mode i.e. with
config.cache_classes = true
however it does not work in development with cache_classes set to false.
The error thrown is
ArgumentError (A copy of MtLib::DBValidations has been removed from
the module tree but is still active!):
My question is what is the process that is followed when cache_class is set to false. Does Rails re-run any of the initialization methods? If not then where is the best place for me to put my patch to ensure that it is in all models and survives a classes reload?
I have tried adding the patch to config/initializers/active_record_patch, however this is not re-run when the classes are reloaded.
The solution to this, provided by Frederick Cheung on the Ruby On Rails google group add the directory containing the loaded class into the load_once_path array.
I edited environment.rb to look like this
config.load_paths +=
%W( #{RAILS_ROOT}/lib/soap_clients/carefone #{RAILS_ROOT}/lib/mt_lib)
# Make sure load_once_paths is a subset of load_paths
config.load_once_paths += %W( #{RAILS_ROOT}/lib/mt_lib)
And now this works in development mode without having to reload the server on every request