I am pretty new to Rails.
Rails automatically reloads classes and modules if application files in the autoload paths change.
(I don't change any files at this moment)
In my test,
a simple /foo request will always take around 200ms to response when config.cache_classes = false.
the simple /foo request can down to 60ms in the second hit when config.cache_classes = true.
will config.cache_classes = false. cache the class and modules in the ruby process memory,
if yes, why it was still 200ms instead of 60ms after the first hit
when config.cache_classes = false.
if no , why we need auto reload since it will always look up in the
file system for the change.
I got confused by this behavior, Any help is appreciated.
Related
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 recently started having to restart my development server every time I change my code. My development.rb file still has this line:
config.cache_classes = false
I tried using the debugger verify that this value has stuck around. To do this I set my configuration to a global variable in environment.rb:
$my_initializer = Rails::Initializer.run do |config|
...
end
then I put a debugger line in one of my controllers so I could do this:
(rdb:2) $my_initializer.configuration.cache_classes
false
So that eliminated the possibility that the value of cache_classes was getting set to true somewhere else. I've tried using both Mongrel and WEBrick and it still happens.
What else might be causing Rails not to reload my code with every request?
I am running:
Mongrel 1.1.5
WEBrick 1.3.1
Rails 2.3.8
Ruby 1.8.7 p253
EDIT:
at #Daemin 's suggestion I checked that the mtime of my files are are actually getting updated when I save them in my text editor (Textmate)
merced:controllers lance$ ls -l people_controller.rb
-rwxr-xr-x 1 lance staff 2153 Act 10 18:01 people_controller.rb
Then I made a change and saved the file:
merced:controllers lance$ ls -l people_controller.rb
-rwxr-xr-x# 1 lance staff 2163 Oct 11 12:03 people_controller.rb
So it's not a problem with the mtimes.
So it turns out that config.threadsafe! overwrites the effect of config.cache_classes = false, even though it doesn't actually overwrite the value of cache_classes (see my question for proof). Digging around a bit more in the Rails source code might illuminate why this might be, but I don't actually need threadsafe behavior in my development environment. Instead, I replaced my call to config.threadsafe! in environment.rb to
config.threadsafe! unless RAILS_ENV == "development"
and everything works fine now.
If anyone else has this problem the solution was the order: config.threadsafe! has to come before config.cache_classes. Reorder it like this to fix it:
...
config.threadsafe!
config.cache_classes = false
...
answer from: Rails: cache_classes => false still caches
I suspect that the classes you are expecting to refresh have been 'required' somewhere in your configuration. Note that Rails' dependency loading happens after Ruby's requires have happened. If a particular module or class has already been required, it will not be handled by Rails' dependency loader, and thus it will not be reloaded. For a detailed explanation, check out this article: http://spacevatican.org/2008/9/28/required-or-not
Despite the fact that the threadsafe! solution works, I also wanted to point out for your benefit and the others that may come in after the following...
If you're editing engine code that is directly in your vendor/engines directory, those files will not be updated without a restart. There may be a configuration option to enable such functionality. However, this is very important to remember if you have used engines to separate large bits of functionality from your application.
My guess would be that it's not reloading the classes for each request because they haven't changed between requests. So the system would note down the last modified time when the classes are loaded, and not reload them until that changed.
Is it true that the standard way to say "cache all Model, View, Controller code" when running the Rails server, by using the following line in config/environments/development.rb
config.cache_classes = true
and for don't cache any of them:
config.cache_classes = false
and to "selectively" cache any one of them, use the above false line, and in config/environment.rb:
config.load_once_paths += %W( #{RAILS_ROOT}/app/models )
which will only cache the Model code. And to cache Controller code or View code, just add either
#{RAILS_ROOT}/app/controllers
or
#{RAILS_ROOT}/app/views
to inside the %W{ }. For example, if we are only developing the Views (HTML and CSS), then there is no need to reload
Model and Controller code when running the server, so set load_once_paths for Models and Controllers,
and just let the View code load every time? (is there docs that talk about this?)
Well, there is no documentation that explains this in detail, but you can read about rails configuration here : http://guides.rubyonrails.org/configuring.html
As for your question, You are absolutely correct :).
use config.load_once_paths to cache selectively ( Obviously with config.cache_classes = false )
And use config.cache_classes = true to cache everything
I was just wondering and didn't find explicit response on what in the model class (ActiveRecord) is cached when setting config.cache_classes to true ?
Could someone tell me or point me to the doc I didn't found ?
Thanks
It determines whether or not your application classes are reloaded on each request. If it's true, you have to restart your server for code changes to take effect (i.e. you set it to true in production, false in development.)
Documentation is here.
What is cached when using config.cache_classes = true
It responsible for two thing in rails 4
1. It prevent class reloading between requests.
2. It ensure Rack::Lock in not included in middleware stack, so
that your thread don't get locked.
In my config/environments/development.rb I have the following line:
config.action_controller.consider_all_requests_local = true
which means I should get all the ugly error stuff when in development environment. But for some reason my app has suddenly started giving me the pretty error page you're supposed to see on production.
Is there possibly some place where this may have been over-ridden? Other people are working on the project as well so maybe one of them did something to cause it.
Old post, but just in case someone finds this like I did ...
I'm pretty sure that when the
config.action_controller.consider_all_requests_local = true
is set, local_request? is never called.
I would dump the config value at runtime and see what it is.
How do I access a Rails configuration value during runtime?
(in rails 3.2)
config.consider_all_requests_local = true
Someone might be overriding the local_request? (api) method somewhere, it's a way to always show the proper error page.
I just answered someone else's question on how to override it. You basically just would put a method in one of the controllers (like ApplicationController) like this:
def local_request?
false
end
So, possibly someone used that somewhere. Do a full project search in textmate or using grep.
This just happened to me and it turned out it was just because I had special characters in the page I was trying to load. I added # encoding: utf-8 to the top of the file with the special characters and everything worked.