Currently, as far as I can tell, plugins are not reloaded in development mode, making a teeny bit of a pain when you''re developing them. This stems from the fact that plugins'' init.rb files are only loaded during the initial "plugin load phase" in the Initializer (line 91 of railsties/lib/initializer.rb in the current HEAD rails). If anyone is using their init.rb to send :include messages to objects, they''re going to lose this functionality on the second request. With the provision that I''m right about this, are there any plans to do any kind of plugin reloading in development mode? Cheers james
Hi James, comments below: On 3-Nov-05, at 9:57 AM, James Adam wrote:> Currently, as far as I can tell, plugins are not reloaded in > development mode, making a teeny bit of a pain when you''re developing > them. This stems from the fact that plugins'' init.rb files are only > loaded during the initial "plugin load phase" in the Initializer (line > 91 of railsties/lib/initializer.rb in the current HEAD rails). > > If anyone is using their init.rb to send :include messages to objects, > they''re going to lose this functionality on the second request. With >That''s a pretty sweeping statement. Isn''t it just the case for *descendants* of ActiveRecord, ActionController and ActionMailer? Are you really sending :include to descendants of those classes or are you just running in to the recent change in AR that patches a memory leak by removing AR::Base subclasses'' methods and variables on an application reset?> the provision that I''m right about this, are there any plans to do any > kind of plugin reloading in development mode? >Personally I''d say that *automatic* reloading for each request in dev mode is a bad idea. I would be much more comfortable if it were possible to explicitly register for notification of events like :application_init and :application_reset or the like - dealing with reloading only if I had to. Regards, Trevor -- Trevor Squires http://somethinglearned.com
Hi Trevor - Maybe you can clarify what I''m talking about with reference to a simple example. Say that within the application proper we have a class (user.rb) along the lines of class User < ActiveRecord::Base .... end and somebody write a plugin which contains a module module MyModule ... end ...designed to enhance that object. Two possibly options for making the module functions available to instances of User are either: Explicitly - edit the user.rb to add "include MyModule" Implicitly - in the plugin''s init.rb, do something like "User.send(:include, ''MyModule'')" (or User.class_eval do include MyModule end .... and probably many more ways) The second option might be more appealing to some developers, because it means that users can drop in plugins without further user intervention. However, because the plugin init.rb file is only read at load time, when the User class is cleaned and reloaded, it will lose all of the MyModule functionality because the only place the include is defined is in a file which is never loaded again. The question is this: is there any way to use the second technique of extending ActiveRecord (or other ActionWhatever) objects in such a way that survives the development reload process? - james On 11/3/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote:> Hi James, > > comments below: > > On 3-Nov-05, at 9:57 AM, James Adam wrote: > > > Currently, as far as I can tell, plugins are not reloaded in > > development mode, making a teeny bit of a pain when you''re developing > > them. This stems from the fact that plugins'' init.rb files are only > > loaded during the initial "plugin load phase" in the Initializer (line > > 91 of railsties/lib/initializer.rb in the current HEAD rails). > > > > If anyone is using their init.rb to send :include messages to objects, > > they''re going to lose this functionality on the second request. With > > > > That''s a pretty sweeping statement. Isn''t it just the case for > *descendants* of ActiveRecord, ActionController and ActionMailer? > > Are you really sending :include to descendants of those classes or are > you just running in to the recent change in AR that patches a memory > leak by removing AR::Base subclasses'' methods and variables on an > application reset? > > > the provision that I''m right about this, are there any plans to do any > > kind of plugin reloading in development mode? > > > > Personally I''d say that *automatic* reloading for each request in dev > mode is a bad idea. > > I would be much more comfortable if it were possible to explicitly > register for notification of events like :application_init and > :application_reset or the like - dealing with reloading only if I had > to. > > Regards, > Trevor > > -- > Trevor Squires > http://somethinglearned.com > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Hi again, comments below: On 3-Nov-05, at 12:17 PM, James Adam wrote:> > class User < ActiveRecord::Base .... end > > and somebody write a plugin which contains a module > > module MyModule ... end > > ...designed to enhance that object. Two possibly options for making > the module functions available to instances of User are either: >So, I can interpret this in two ways: 1 - MyModule is designed to enhance User (and only User) 2 - MyModule is designed to enhance AR::Base> Explicitly - edit the user.rb to add "include MyModule" > Implicitly - in the plugin''s init.rb, do something like > "User.send(:include, ''MyModule'')" (or User.class_eval do include > MyModule end .... and probably many more ways) > > The second option might be more appealing to some developers, because > it means that users can drop in plugins without further user > intervention. However, because the plugin init.rb file is only read at > load time, when the User class is cleaned and reloaded, it will lose > all of the MyModule functionality because the only place the include > is defined is in a file which is never loaded again. >The statement "drop in plugins without further user intervention" is significant here. In your above example that would mean that MyModule is designed to enhance User (and only User). Otherwise, you''d *have* to have something *somewhere* that said "enhance User with MyModule" right? Assuming *zero*-intervention is your goal and assuming that User is purely a domain object (my hints being that it reloads and it inherits from AR::Base), what is the point of using plugins as a mechanism to enhance it? Where else is that plugin useful other than the current project? I''m not sure your User and MyModule example was intended to be truly zero-intervention. I believe that true zero-intervention is impossible in most cases. One exception that springs to mind is the asset timestamping plugin because it transparently (and non-destructively) alters part of rails'' guts in a way that the developer can safely ignore. Of course, I''m sure there may be other scenarios for zero-intervention that haven''t occurred to me. As for how users ''intervene'' to enhance their classes, that''s a matter of personal taste. Do you inject an "acts" into AR::Base and make the plugin consumer say "acts_as_chunky_bacon" or do you get them to "include ''MyModule''"? Or do you have something (?) that init.rb uses to send :include calls to nominated classes? Or to put it another way, should users edit *their* code or the *plugin''s* code to enhance their own classes. Personally I''ve chosen the path of least resistance because a) it''s the path of least resistance, and b) I think it''s familiar and it makes it clearer what''s happening: if a user wants to enhance their classes with my plugin, they edit their own code. But like I said, that''s a matter of personal taste, which brings me to:> The question is this: is there any way to use the second technique of > extending ActiveRecord (or other ActionWhatever) objects in such a way > that survives the development reload process? >For ActiveRecord there is a way to survive the reload process. If your AR class defines: def reloadable? false end It survives the reload process (because it never unloads). For AR objects that you define in a plugin this is fine (imho) because it''s library code that should be static so doesn''t need to reload anyways. For AR objects that are in the user''s models directory and are enhanced by a plugin, this is less than optimal because they''ve lost the reload ability. With all that blathering I just wanted to finish of by saying that if *your* life would be made easier by plugins reloading in dev mode that''s completely understandable. As I said before though, I think an automatic reload is a bad idea and I''d have trouble standing up saying "that feature is needed". However, something opt-in like registering for event notification about stuff like :appication_init or :application_reset would put the right tool in the hands of the people that wanted it. Does that seem reasonable? Regards, Trevor> - james > > On 11/3/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote: >> Hi James, >> >> comments below: >> >> On 3-Nov-05, at 9:57 AM, James Adam wrote: >> >>> Currently, as far as I can tell, plugins are not reloaded in >>> development mode, making a teeny bit of a pain when you''re developing >>> them. This stems from the fact that plugins'' init.rb files are only >>> loaded during the initial "plugin load phase" in the Initializer >>> (line >>> 91 of railsties/lib/initializer.rb in the current HEAD rails). >>> >>> If anyone is using their init.rb to send :include messages to >>> objects, >>> they''re going to lose this functionality on the second request. With >>> >> >> That''s a pretty sweeping statement. Isn''t it just the case for >> *descendants* of ActiveRecord, ActionController and ActionMailer? >> >> Are you really sending :include to descendants of those classes or are >> you just running in to the recent change in AR that patches a memory >> leak by removing AR::Base subclasses'' methods and variables on an >> application reset? >> >>> the provision that I''m right about this, are there any plans to do >>> any >>> kind of plugin reloading in development mode? >>> >> >> Personally I''d say that *automatic* reloading for each request in dev >> mode is a bad idea. >> >> I would be much more comfortable if it were possible to explicitly >> register for notification of events like :application_init and >> :application_reset or the like - dealing with reloading only if I had >> to. >> >> Regards, >> Trevor >> >> -- >> Trevor Squires >> http://somethinglearned.com >> >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Trevor Squires http://somethinglearned.com
I''ll try and keep this short... ;-) Event notification & method hooks a-la :application_init - definitely a good idea. It would open up avenues to solving many problems, including but not limited to "plugin/init.rb files being run beyond when the server starts", should such a thing ever be advisable or required. Zero-intervention: You''re right, and I''ve been 98.3% convinced. For the User object example, I''ve come around to your argument that it''s better for the developer to explicitly ''include'' the Modules so they know exactly what they''re getting into. Less confusing for debugging odd behaviour when you can''t be sure whether it originated in your model or something you''ve mixed-in, too. Would there ever be a case there one plugin might want to interfere with the behaviour of another plugin? That might be the only real ''strong'' case for making zero-intervention work, since IMHO you should never, ever have to modify the code of a well designed plugin (hence, to some extent, Rails Engines). But that might never be sensible anyway. And I''ve been known to be spectacularly wrong. FYI, this is all stemming from the development of a multi-layered user security/authentication/RBAC Engine, where I''m trying to impose as little as possible on the application schema and reuse as much code from existing systems at the same time. Thanks for thrashing this out with me, I definitely feel happier about what''s going on with the plugins in development mode. Cheers! james On 11/3/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote:> Hi again, > > comments below: > > On 3-Nov-05, at 12:17 PM, James Adam wrote: > > > > class User < ActiveRecord::Base .... end > > > > and somebody write a plugin which contains a module > > > > module MyModule ... end > > > > ...designed to enhance that object. Two possibly options for making > > the module functions available to instances of User are either: > > > > So, I can interpret this in two ways: > > 1 - MyModule is designed to enhance User (and only User) > 2 - MyModule is designed to enhance AR::Base > > > Explicitly - edit the user.rb to add "include MyModule" > > Implicitly - in the plugin''s init.rb, do something like > > "User.send(:include, ''MyModule'')" (or User.class_eval do include > > MyModule end .... and probably many more ways) > > > > The second option might be more appealing to some developers, because > > it means that users can drop in plugins without further user > > intervention. However, because the plugin init.rb file is only read at > > load time, when the User class is cleaned and reloaded, it will lose > > all of the MyModule functionality because the only place the include > > is defined is in a file which is never loaded again. > > > > The statement "drop in plugins without further user intervention" is > significant here. In your above example that would mean that MyModule > is designed to enhance User (and only User). Otherwise, you''d *have* > to have something *somewhere* that said "enhance User with MyModule" > right? > > Assuming *zero*-intervention is your goal and assuming that User is > purely a domain object (my hints being that it reloads and it inherits > from AR::Base), what is the point of using plugins as a mechanism to > enhance it? Where else is that plugin useful other than the current > project? > > I''m not sure your User and MyModule example was intended to be truly > zero-intervention. > > I believe that true zero-intervention is impossible in most cases. One > exception that springs to mind is the asset timestamping plugin because > it transparently (and non-destructively) alters part of rails'' guts in > a way that the developer can safely ignore. > > Of course, I''m sure there may be other scenarios for zero-intervention > that haven''t occurred to me. > > As for how users ''intervene'' to enhance their classes, that''s a matter > of personal taste. Do you inject an "acts" into AR::Base and make the > plugin consumer say "acts_as_chunky_bacon" or do you get them to > "include ''MyModule''"? Or do you have something (?) that init.rb uses > to send :include calls to nominated classes? > > Or to put it another way, should users edit *their* code or the > *plugin''s* code to enhance their own classes. > > Personally I''ve chosen the path of least resistance because a) it''s the > path of least resistance, and b) I think it''s familiar and it makes it > clearer what''s happening: if a user wants to enhance their classes with > my plugin, they edit their own code. > > But like I said, that''s a matter of personal taste, which brings me to: > > > The question is this: is there any way to use the second technique of > > extending ActiveRecord (or other ActionWhatever) objects in such a way > > that survives the development reload process? > > > > For ActiveRecord there is a way to survive the reload process. If your > AR class defines: > > def reloadable? > false > end > > It survives the reload process (because it never unloads). For AR > objects that you define in a plugin this is fine (imho) because it''s > library code that should be static so doesn''t need to reload anyways. > For AR objects that are in the user''s models directory and are enhanced > by a plugin, this is less than optimal because they''ve lost the reload > ability. > > With all that blathering I just wanted to finish of by saying that if > *your* life would be made easier by plugins reloading in dev mode > that''s completely understandable. > > As I said before though, I think an automatic reload is a bad idea and > I''d have trouble standing up saying "that feature is needed". However, > something opt-in like registering for event notification about stuff > like :appication_init or :application_reset would put the right tool in > the hands of the people that wanted it. Does that seem reasonable? > > Regards, > Trevor > > > - james > > > > On 11/3/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote: > >> Hi James, > >> > >> comments below: > >> > >> On 3-Nov-05, at 9:57 AM, James Adam wrote: > >> > >>> Currently, as far as I can tell, plugins are not reloaded in > >>> development mode, making a teeny bit of a pain when you''re developing > >>> them. This stems from the fact that plugins'' init.rb files are only > >>> loaded during the initial "plugin load phase" in the Initializer > >>> (line > >>> 91 of railsties/lib/initializer.rb in the current HEAD rails). > >>> > >>> If anyone is using their init.rb to send :include messages to > >>> objects, > >>> they''re going to lose this functionality on the second request. With > >>> > >> > >> That''s a pretty sweeping statement. Isn''t it just the case for > >> *descendants* of ActiveRecord, ActionController and ActionMailer? > >> > >> Are you really sending :include to descendants of those classes or are > >> you just running in to the recent change in AR that patches a memory > >> leak by removing AR::Base subclasses'' methods and variables on an > >> application reset? > >> > >>> the provision that I''m right about this, are there any plans to do > >>> any > >>> kind of plugin reloading in development mode? > >>> > >> > >> Personally I''d say that *automatic* reloading for each request in dev > >> mode is a bad idea. > >> > >> I would be much more comfortable if it were possible to explicitly > >> register for notification of events like :application_init and > >> :application_reset or the like - dealing with reloading only if I had > >> to. > >> > >> Regards, > >> Trevor > >> > >> -- > >> Trevor Squires > >> http://somethinglearned.com > >> > >> _______________________________________________ > >> Rails mailing list > >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > >> http://lists.rubyonrails.org/mailman/listinfo/rails > >> > > _______________________________________________ > > Rails mailing list > > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > > -- > Trevor Squires > http://somethinglearned.com > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >