Extending a class from plugin, need always restart server?


#1

Hi there,

So, I’ve got a class from a plugin installed in /vendor/plugins. I want
to change it a bit, customizing how it works, so I’ve created a file
(/lib/myextension.rb):

class TheClass
 def somestuff
end
end

Then, I required the file from my environment.rb:

require 'lib/myextension'

Here’s my question. Every time I change my class extension, I get
errors…seems like I need to restart my web server (or script/console)
with every change, which is making development very slow.

In script/console I’ve tried “reload!”, and it doesn’t seem to help. I
put “include Reloadable” into the class and that doesn’t seem to help
either.

Am I missing something??

Thanks in advance!!

Cameron

pw. The error I get after making a change is:

undefined method `somestuff' for Comatose::Page:Class

#2

Cameron B. wrote:

Hi there,

So, I’ve got a class from a plugin installed in /vendor/plugins. I want
to change it a bit, customizing how it works, so I’ve created a file
(/lib/myextension.rb):

class TheClass
 def somestuff
end
end

Then, I required the file from my environment.rb:

require 'lib/myextension'

Here’s my question. Every time I change my class extension, I get
errors…seems like I need to restart my web server (or script/console)
with every change, which is making development very slow.

In script/console I’ve tried “reload!”, and it doesn’t seem to help. I
put “include Reloadable” into the class and that doesn’t seem to help
either.

Am I missing something??

Well, maybe you can put the code that you are developing closer to were
you can see how it works during development, e.g. a controller, or
model, and then move it out into the lib directory once you are
satisfied with its functionality.

Or, you could develop it against a unit test. When running tests your
lib entries are reloaded. And you’d have a nice way to see that your
changes are still good once the next release of Comatose comes along.

Stephan

Thanks in advance!!

Cameron

pw. The error I get after making a change is:

undefined method `somestuff' for Comatose::Page:Class

#3

Stephan W. wrote:

Well, maybe you can put the code that you are developing closer to were
you can see how it works during development, e.g. a controller, or
model, and then move it out into the lib directory once you are
satisfied with its functionality.

Or, you could develop it against a unit test. When running tests your
lib entries are reloaded. And you’d have a nice way to see that your
changes are still good once the next release of Comatose comes along.

Hi Stephan,

So my attempt at generalization has given me away as extending comatose.
:wink: No worries there, Comatose is great!!

Thanks for the suggestions. The unit testing idea makes sense to me for
sure, and is a good suggestion.

As for straight development (not in /test), since I’m extending the
comatose page class, and view controller, I’m using the /lib dir because
I don’t really know where else I should put stuff like this. Would it
make sense to put this stuff in app/models and app/controllers even
though they aren’t full-on models/controllers, but just opening up a
model/controller class and adding methods?

Does rails reload everything in the app/models and app/controllers
folders on each load, but not the /lib stuff?

Thanks!


#4

Cameron B. wrote:

Stephan W. wrote:

Well, maybe you can put the code that you are developing closer to were
you can see how it works during development, e.g. a controller, or
model, and then move it out into the lib directory once you are
satisfied with its functionality.

Or, you could develop it against a unit test. When running tests your
lib entries are reloaded. And you’d have a nice way to see that your
changes are still good once the next release of Comatose comes along.

Hi Stephan,

So my attempt at generalization has given me away as extending comatose.
:wink: No worries there, Comatose is great!!

Thanks for the suggestions. The unit testing idea makes sense to me for
sure, and is a good suggestion.

As for straight development (not in /test), since I’m extending the
comatose page class, and view controller, I’m using the /lib dir because
I don’t really know where else I should put stuff like this. Would it
make sense to put this stuff in app/models and app/controllers even
though they aren’t full-on models/controllers, but just opening up a
model/controller class and adding methods?

/vendor is for non-app specific code from others – /lib for your
non-app specific code.

I don’t know what you’re doing, but my (first) suggestion was you could
put the code you are developing straight into any model/controller
you’re working with, as long as you know how to extract it into the lib
directory when you’re done.

If Rick Olsen’s recommendation works out for you, maybe you don’t need
to go through this, and you should first properly hook up the changes
you’re applying to Comatose. (“Don’t know what you’re doing.”)

See you

Stephan

Does rails reload everything in the app/models and app/controllers
folders on each load, but not the /lib stuff?

Thanks!


#5

On 2/1/07, Cameron B. removed_email_address@domain.invalid wrote:

changes are still good once the next release of Comatose comes along.
comatose page class, and view controller, I’m using the /lib dir because
I don’t really know where else I should put stuff like this. Would it
make sense to put this stuff in app/models and app/controllers even
though they aren’t full-on models/controllers, but just opening up a
model/controller class and adding methods?

Does rails reload everything in the app/models and app/controllers
folders on each load, but not the /lib stuff?

Thanks!

Rails reloads everything in /lib too if it was autoloaded.

Be careful about extending your rails app classes from plugins.
Remember that the load cycle goes like this: Rails => Plugins => App.
Plugins can safely monkey patch Rails, since neither are reloaded.
However, modifying your app classes can be troublesome. What if
Plugin A includes itself into Post, yet Post has code that depends on
Plugin A and B? You get an error, that’s what.

2 suggestions:

  1. It’s okay to require users to add code to their app to load
    plugins. Requiring a manual “include FooMethods” is fine. It makes
    it more explicit that you’re using a plugin. Common acts_as_* plugins
    will define a single class method on ActiveRecord::Base that does
    little more than setting some options and including some modules.

  2. I wrote a little “include_into” hack to Module.
    http://weblog.techno-weenie.net/2006/11/15/extending-your-rails-classes-from-plugins

I’d advise #1 unless you’re pretty familiar with ruby/rails.


Rick O.
http://weblog.techno-weenie.net
http://mephistoblog.com


#6

Stephan W. wrote:

/vendor is for non-app specific code from others – /lib for your
non-app specific code.

I don’t know what you’re doing, but my (first) suggestion was you could
put the code you are developing straight into any model/controller
you’re working with, as long as you know how to extract it into the lib
directory when you’re done.

If Rick Olsen’s recommendation works out for you, maybe you don’t need
to go through this, and you should first properly hook up the changes
you’re applying to Comatose. (“Don’t know what you’re doing.”)

Thanks for the suggestions Rick, and Stephan. I’m not trying to be
secretive about what I’m doing, just thought being generic would make it
applicable to a wider audience…guess it’s obfuscating the issue.

Basically I have the Comatose plugin, and I want to adjust how the
Comatose::Page model, and the ComatoseController controller work a bit,
but I don’t want to edit those files directly (breaking future upgrade
paths).

My thinking was to create my own app-specific overrides in the /lib
folder, where for each case I just open up the class, fiddle with it how
I need, and that’s it, eg:

lib/comatose_page_overrides.rb

This is intended to override/extend:

vendor/plugins/comatose/lib/comatose/page.rb

class Comatose::Page
def some_new_method
# do my new stuff
end

def some_existing_method
# override how plugin works by default
end
end

My overrides are working how I want, it’s just the need to restart the
server with each change I make to the file. The difficulty I’m having is
somehow related to the fact that rails plugins aren’t reloaded
automatically on each call, yet I want my overrides to be reloaded
automatically.

I’ll look into the stuff you both mention though and see if I can figure
it out :wink:

Cameron