Hey guys. I’m writing an “acts_as_X” plugin that’s used by
controllers. Unfortunately, the plugin isn’t being reloaded for each
request [in the dev env].
I thought that adding
config.reload_plugins = true if RAILS_ENV == ‘development’
to environment.rb , as well as
require ‘acts_as_X’
to my plugin’s init.rb would do the trick, but it doesn’t.
Is there a way to configure Rails to reload the plugin for each request?
Just for your enlightenment, a big part of the problem is that you
were including your module in ActionController::Base. This was
problematic because the rails framework (including
ActionController::Base) doesn’t get reloaded, but you were forcing
Rails to reload your module event though ActionController::Base was
still hanging onto it (you wouldn’t have had this issue if you’d
included it in ApplicationController. Using require rather than
require_dependency sidesteps Rails’ dependency stuff (which is the
thing that manages code reloading)
Hey Frederick. Thanks for the tip. That makes sense. It turns out that
I didn’t completely solve the problem of the plugin reloading, and I
think what you described is the culprit.
For some reason, ActsAsDashboard::ClassMethods is not being reloaded
for each request.
I tried your suggestion of changing the plugin’s init.rb from this:
require ‘acts_as_dashboard’
ActionController::Base.send :include, ActsAsDashboard
to this:
require ‘acts_as_dashboard’
ApplicationController.send :include, ActsAsDashboard
However, every request other than the first results in this error:
“undefined local variable or method `acts_as_dashboard’ for
DashboardsController:Class”
citing line 2 of app/controllers/dashboards_controller.rb :
1 class DashboardsController < ApplicationController
2 acts_as_dashboard
Might you know what needs to be done to get Rails to reload
ActsAsDashboard::ClassMethods for each request?
The answer’s dead easy. Those child modules and classes need to split
out into separate files. So ActsAsDashboard::Config must be in lib/
acts_as_dashboard/config.rb , ActsAsDashboard::ClassMethods must be in
lib/acts_as_dashboard/class_methods.rb , etc.
Once I did that, everything in the plugin was reloaded.
to this:
Might you know what needs to be done to get Rails to reload
ActsAsDashboard::ClassMethods for each request?
Thanks, mate!
Nick
Whoops, I sent that last email a bit prematurely. After switching to
using
ApplicationController.send :include, ActsAsDashboard
in init.rb , this error:
undefined local variable or method `acts_as_dashboard’ for
DashboardsController:Class"
was occuring on subsequent requests because init.rb is only run when
the web server is started; it isn’t run before any web requests.
So on the first request, ActsAsDashboard has been loaded, and life’s
peachy. But on the 2nd request, all of those non-Rails framework
classes (such as ApplicationController, DashboardsController, etc) are
unloaded and then loaded. However, because my init.rb isn’t executed,
ActsAsDashboard isn’t included into ApplicationController. Thus, #acts_as_dashboard isn’t available to DashboardsController, and the
error above occurs.
I’ve found that putting
include ActsAsDashboard
into DashboardsController gets rid of the error above, and results in
ActsAsDashboard::ClassMethods being reloaded for each request.
However, that’s only a short-term solution.
If you want something to be reloadable you should use
require_dependency to load it. The main thing though is that a
plugin’s init.rb is not re-run between requests, so the include you do
on ApplicationController is lost after the first request.
Fred
Right. So how can one get a module included in a controller on
subsequent requests without explicitly putting an #include in the
controller?
To facilitate development (IE: not restart WEBrick between requests),
I have this at the moment:
class DashboardsController < ApplicationController
include ActsAsDashboard
acts_as_dashboard
I’d like to figure out how to remove that #include . Any ideas?
However, every request other than the first results in this error:
“undefined local variable or method `acts_as_dashboard’ for
DashboardsController:Class”
citing line 2 of app/controllers/dashboards_controller.rb :
1 class DashboardsController < ApplicationController
2 acts_as_dashboard
Might you know what needs to be done to get Rails to reload
ActsAsDashboard::ClassMethods for each request?
If you want something to be reloadable you should use
require_dependency to load it. The main thing though is that a
plugin’s init.rb is not re-run between requests, so the include you do
on ApplicationController is lost after the first request.
Right. So how can one get a module included in a controller on
subsequent requests without explicitly putting an #include in the
controller?
To facilitate development (IE: not restart WEBrick between requests),
I have this at the moment:
class DashboardsController < ApplicationController
include ActsAsDashboard
acts_as_dashboard
I’d like to figure out how to remove that #include . Any ideas?
I suppose you could define self.inherited on ActionController::Base
and do your setup from there.
Fred
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.