Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #5852 (closed defect: fixed)

Opened 3 years ago

Last modified 1 year ago

Problem with dependencies and plugins

Reported by: contact@lukeredpath.co.uk Assigned to: ulysses
Priority: high Milestone: 1.2
Component: ActionPack Version: 1.1.1
Severity: critical Keywords: plugins dependencies modules
Cc: bitsweat, t.lucas@toolmantim.com

Description

I'll paste more or less what I sent to the core list so we can move discussion here, as per Nicholas's email to the list today about filing tickets.

The new dependencies system seems to completely break the loading of one of the plugins I'm working on, the unobtrusive_javascript plugin (though I don't think this is isolated to our plugin - see the comments on http://weblog.rubyonrails.org/2006/8/11/reloading-revamped/).

The plugin's init.rb requires all of the necessary files, one of which is vendor/plugins/unobtrusive_javascript/lib/unobtrusive_javascript.rb - this file contains a module called UnobtrusiveJavascript.

This module contains a method which needs to be used in the routes.rb file, UnobtrusiveJavascript::routes. This worked fine before. However it fails to work and I get the following strange error:

Expected /Users/luke/Sandbox/projects/rails_plugin_repository/config/../vendor/plugins/unobtrusive_javascript/lib/unobtrusive_javascript.rb to define UnobtrusiveJavascript

The problem doesn't seem to be related to the method being called in routes - if I remove the line it fails to find the apply_behaviour method which is in PLUGIN_ROOT/lib/unobtrusive_javascript/helpers.rb, inside a module called UnobtrusiveJavascript::Helpers. These helpers are injected in the init.rb file:

ActionController::Base.send(:helper, UnobtrusiveJavascript::Helpers)

This did use to work.

Change History

08/22/06 09:37:42 changed by bitsweat

  • cc set to bitsweat.

Curious - as a shot in the dark, could you try changing the plugin directory name so it doesn't clash with the module name?

Also, set Dependencies.log_activity = true and watch the log at plugin load time.

08/22/06 09:39:56 changed by anonymous

Hi Jeremy - I'll give that a go tomorrow. You think perhaps a problem is being caused by it trying to look in /unobtrusive_javascript/unobtrusive_javascript?

08/22/06 21:53:02 changed by anonymous

acts_as_paranoid and acts_as_attachment load correctly on the first request. Subsequent requests fail after that with:

./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:186:in `load_missing_constant': A copy of Technoweenie::ActsAsAttachment::ActMethods has been removed from the module tree but is still active!

Personally I don't see the need to make plugins reloadable like the rest of rails in dev mode. But I suppose for plugin developers is is a nice feature.

08/22/06 22:04:48 changed by contact@lukeredpath.co.uk

Having plugins reloadable in development is certainly convenient, but I'd take a working dependencies system with server restarts for plugin changes over reloadable plugins.

08/23/06 01:26:26 changed by ulysses

luke: unobtrusive js seems to work fine for me, but I'm not doing much with it. Could you offer some assistance reproducing it on latest trunk?

08/25/06 10:03:59 changed by t.lucas@toolmantim.com

I'm having the same problem with a few other plugins (most notably auto-admin) where it's reloading the AutoAdmin::Configuration module with each request. Any way to mark as a module as not reloadable?

08/25/06 10:11:24 changed by t.lucas@toolmantim.com

  • cc changed from bitsweat to bitsweat, t.lucas@toolmantim.com.

08/29/06 06:52:40 changed by ulysses

(In [4837]) Update Initializer to use load_once_paths to avoid plugin reloading. References #5852. Add Dependencies.load_once_paths.

08/31/06 16:41:58 changed by rick

  • status changed from new to closed.
  • resolution set to fixed.

Mephisto and all its wonderful plugins work fine. I'm closing for now. Please reopen if you still have this issue.

08/31/06 23:24:55 changed by contact@lukeredpath.co.uk

OK, there was still a problem with the UJS plugin, which *may* need looking at. However I'll leave the ticket closed for now as I was able to come up with a simple workaround.

The UJS plugin is in vendor/plugins/unobtrusive_javascript; it uses a module called UnobtrusiveJavascript which is first created in PLUGIN_ROOT/lib/unobtrusive_javascript.rb and contains other files inside the module in PLUGIN_ROOT/lib/unobtrusive_javascript/ - this seemed to confuse Rails for some reason.

I was able to fix things by renaming the module throughout the plugin to UJS, renaming lib/unobtrusive_Javascript.rb to lib/ujs.rb and lib/unobtrusive_Javascript/ to lib/ujs. All now seems to be fine.

09/01/06 03:48:49 changed by vinbarnes@gmail.com

  • status changed from closed to reopened.
  • resolution deleted.

I experience a problem with the acts_as_authenticated plugin mechanism. The problem is actually not with the plugin but with the resulting library that it creates, lib/authenticated_system.rb and reloading of modules when testing via script/console. (I cannot recreate the problem in development against script/server.)

I get the error, ArgumentError (A copy of AuthenticatedSystem has been removed from the module tree but is still active!):

In dependencies.rb, the call to qualified_const_defined? inside the load_missing_constant method reports that AuthenticatedSystem is still hanging around. Looking at the development log reveals that it has indeed been removed (or at least reports that it has been removed): Dependencies: removing constant AuthenticatedSystem

09/03/06 02:44:43 changed by jay@jay.fm

config.load_once_paths apparently needs to be set in environment.rb itself; it can't be set in, say, environment/test.rb where it might be more useful. Is that intended behavior?

09/03/06 18:01:22 changed by ulysses

vinbarnes@gmail.com: Can you please open a new ticket, since this appears to be a different issue?

Also, ApplicationController was not reloading properly, so it may have been causing these problems. It was fixed in [4910].

09/07/06 18:00:08 changed by ulysses

Jay: You can probably manipulate Dependencies.load_paths directly; however it's probably not a good idea to encourage that.

The main problem with people doing so is that load_paths and load_once_paths ought to be uniq -- Perhaps we should replace config.autoload_paths and config.load_once_paths with something like this:

class UniqEnumerableProxy
  include BlankSlate
  
  def initialize(delegate)
    @delegate = delegate
  end
    
  def method_missing(selector, *args, &proc)
    result = @delegate.send(selector, *args, &proc)
    @delegate.uniq!
    return result
  end
  
  def respond_to?(selector)
    @delegate.respond_to? selector
  end 
  
end

09/20/06 17:41:55 changed by ulysses

Closing; open new tickets for new issues.

09/20/06 17:42:01 changed by ulysses

  • status changed from reopened to closed.
  • resolution set to fixed.

12/28/07 21:07:20 changed by andrewroth

This may work now in the sense that it doesn't crash, but it's a real pain for me to not be able to have my plugin code reloadable. Why not allow plugins to specify if they want to have all their code reloadable in the init.rb?