Activeadmin: ApplicationController and Helpers are not being reloaded in Dev Env

Created on 28 Oct 2011  路  37Comments  路  Source: activeadmin/activeadmin

why is the application_controller cached?
and how can i disable this?

cheers

awaiting developer action bug class reloading

Most helpful comment

Curiously, helpers will reload if you manually define them

ActiveAdmin.register Blah do
  controller { helper BlahHelper }
end

All 37 comments

What exactly is the problem; what do you mean? And how is (caching of) your ApplicationController related to ActiveAdmin?

why its closed?

if i make a change in the application_controller (for example an http_auth for the admin namespace) and i change there something, i have to restart the server. same effect with helpers. they got cache and for each change i have to restart the server

@pcreux I'm having the same problem (v0.4.3)

@fu-media It was closed because you didn't give any details. :)

Could you guys give a try to v0.4.4 with the latest version of inherited resources. This bug might come from inherited resources.

what details you want to have?

i ask why its cached. so i have to restart the server always if i change helpers or application_controller, to take effect in active_admin

its not reloaded on each request

@pcreux I switched to head and application_controller remains cached, I'll try a bundle update inherited_resources and tell you what happens :)

I've been on 1.3.1 of InheritedResources (the latest) for quite awhile and have had this problem ever since forever. It's kind of annoying, especially since my CanCan current_ability method is inside the application controller. I think the helpers not being reloaded is a side-effect of the controller not being reloaded because helpers are all loaded from the application controller.

I'm on AA 0.4.3, Rails 3.2.2, Ruby 1.9.3-p194 (latest I'm aware of).

@pcreux me too, on head activeadmin and latest inherited_resources I get cached application_controller methods

@gregbell was saying that the latest version of Inherited Resources would fix this issue in #342. Looks like he was wrong. :)

@fu-media I don't know why it's cached.

Experiencing this as well.

+1

Curiously, helpers will reload if you manually define them

ActiveAdmin.register Blah do
  controller { helper BlahHelper }
end

Well this is interesting:

div method(:helpers).source_location      # ...gems/arbre-1.0.1/lib/arbre/element.rb21
div method(:helpers).owner                # Arbre::Element
div helpers.method(:blah).source_location # ...app/helpers/blah_helper.rb12
div helpers.method(:blah).owner           # BlahHelper

div "#{blah} -> #{helpers.blah}"          # 1 -> 1

So it's likely that Arbre won't let go of the previously loaded helpers.

Okay, so maybe not. Here's an experiment strictly from rails console:

app_1 = ApplicationController.object_id
derived_1 = UsersController.ancestors.detect {|a| a.to_s =~ /Appli/}.object_id
derived_1 == app_1 # => true

reload!

app_2 = ApplicationController.object_id
derived_2 = UsersController.ancestors.detect {|a| a.to_s =~ /Appli/}.object_id

derived_2 == app_2     # => false
derived_2 == derived_1 # => true

ObjectSpace._id2ref(app_1) # => ApplicationController # Shouldn't exist!!

ObjectSpace._id2ref(app_2) # => ApplicationController 

It's odd that the old ApplicationController still exists... I thought it would be entirely removed from memory.

To illustrate the same thing from the browser:

# 1 changes on file edit, 3 changes on every load, 2 & 4 never change
div controller.class.object_id
div controller.class.ancestors.detect {|a| a.to_s =~ /Appli/}.object_id
div helpers.object_id
div helpers.blah.object_id

Still an issue in 0.6.0

It's possible that #1935 will fix this, though I haven't checked.

To update your helpers automatically, you can temporary hack it like:

Dir["#{ Rails.root }/app/helpers/*.rb"].each { |file| require file }

Just wanted to mention that it's still an issue. ApplicationController is not being reloaded when activeadmin is used (tested with dummy Rails 4.0.2 app with activeadmin in Gemfile).

>> ActiveAdmin::Devise::SessionsController.ancestors.find { |a| a.name =~ /Appl/ }.object_id == ApplicationController.object_id
=> true
>> reload!
Reloading...
=> true
>> ActiveAdmin::Devise::SessionsController.ancestors.find { |a| a.name =~ /Appl/ }.object_id == ApplicationController.object_id
=> false # now we have 2 different ApplicationController-s

But after reloading:

>> Devise::SessionsController.ancestors.find { |a| a.name =~ /Appl/ }.object_id == ApplicationController.object_id
=> true

The solution probably lies deep in Rails' autoloading code :octocat:

Still a problem in 1.0.0.pre1

If someone can make a barebone app on github and provide the steps (manual is fine, doesn't need to be automated) to reproduce it, I can probably take a look!

@chancancode here is a test app to reproduce this bug:
https://github.com/activeadmin/activeadmin_helper_reload_bug
Take a look on the readme
But it should be happen in every activeadmin app too.

1+ on this.

I took a stab at fixing this! PR is linked just above. :smile:

Some notes from @jvaill from #3927:

Just quickly brainstorming, off the top of my head I can think of a few other feasible solutions:

  1. Add the entire lib/ directory to ActiveSupport::Dependencies.autoload_paths and let Rails handle autoloading and reloading. This has the disadvantage of unloading all files inside of lib/ on each request.
  2. Move the controllers to a lib/controllers/ directory and add that to ActiveSupport::Dependencies.autoload_paths.
  3. See if we can use ActiveSupport::Dependencies.explicitly_unloadable_constants to get Rails to explicitly unload the controllers after each request.
  4. ? :smile:

If we'd rather not shuffle files around, then looking into the third option might be worth it.

@chancancode can you take a look on this problem with the test app?
https://github.com/activeadmin/activeadmin_helper_reload_bug
Take a look on the readme
But it should be happen in every activeadmin app too.

There is a very interesting rails issue on how the controllers are supposed to be loaded in gems like AA:
https://github.com/rails/rails/issues/12195

Disconnecting this from the Rails reloading, I can reproduce by simply calling ActiveAdmin.unload!

ObjectSpace.each_object(ActiveAdmin::Resource).count => 17

ActiveAdmin.unload!

ObjectSpace.each_object(ActiveAdmin::Resource).count => 17
ids = ObjectSpace.each_object(ActiveAdmin::Resource).map{ |r| r.controller.object_id }
ids.count                                            => 17

GC.start

ObjectSpace.each_object(ActiveAdmin::Resource).count => 0
ids.count{ |id| ObjectSpace._id2ref id rescue nil }  => 17
ActiveAdmin::BaseController.descendants.count        => 22

ObjectSpace._id2ref(ids.first).name.constantize
-> NameError: uninitialized constant Admin::UsersController

Unload currently does a lot of work to remove the objects from memory, but there must be a reference to the controller somewhere that's not being removed. If only Ruby made it easy to see the references keeping an object in memory...

Well the Mass gem isn't reporting any references.

ids = ObjectSpace.each_object(ActiveAdmin::Resource).map{ |r| r.controller.object_id }
Mass.references Mass[ids.first]
 => {"ActiveAdmin::Resource#70279696346980"=>["@controller"]} 

ActiveAdmin.unload!

Mass.references Mass[ids.first]
 => {}

This didn't seem to help:

ActiveSupport::Dependencies.explicitly_unloadable_constants << 'ActiveAdmin::BaseController'

Might be related - rails code reloading becomes slower with each reload, when anything is present in app/admin folder

To reproduce:

 100.times { puts Benchmark.measure { reload! } }

For one app I have, with 100+ activeadmin modules, it is 2s for first reload, 4s for second, and up to 2-3 minutes to complete hang in 10-15 reloads.

@glebtv not sure if this is the right issue to report, but i am experiencing the same issue with AA 1.4.3, rails 5.2.2.
Forced to re-start rails app after a few changes while developing admin part of application or otherwise it becomes unusable.
Is there something that can be done to address it? Thanks.

No news here, but I've seen several development environment memory leaks fixed in Rails recently, so maybe Rails 6 brings new hope here.

In particular, there's https://github.com/rails/rails/issues/32892 and a related open PR. It'd be good if some hitting this problem could try that patch!

Trying a patch from merged PR https://github.com/rails/rails/pull/31442/files indeed increased reload speed of application, but now activeadmin does not reloads in dev env on files (app/admin/*) change, changes respected only after server restart, any idea where to dig regards this?
Thanks!

Hello, everyone! Facing this issue in my project. Really need to DRY my code in some AA views with helpers. Is there any temporary hack for this issue? This hack seems not to work for me:

To update your helpers automatically, you can temporary hack it like:

Dir["#{ Rails.root }/app/helpers/*.rb"].each { |file| require file }
Was this page helpful?
0 / 5 - 0 ratings