Max Schubert
2011-May-05 03:56 UTC
Better way to force some classes to be eager loaded in development mode with Rails 3.0.5 and class caching off?
Hi, Spent a fair number of hours working out this issue and while I have a working solution I am not happy with it - it feels really really dirty. We define a custom ActiveRecord sub-class that is used by a number of our data models that has a custom self.inherited method to register the sub-classes with the super class as we have super-class level operations that iterate across all of the sub-classes - factory-like class methods. From our custom sub-class of ActiveRecord::Base # Add all X classes to class-level array for use # in class methods that generate X for all sub-classes. def self.inherited(klass) if (klass.class != X) and (klass.class.to_s !~ /^X/) @@x_classes.push klass end # Chain to super or AR classes break! super(klass) end this works really well for our purposes when class caching is on - however, with class caching off in development mode, the callbacks do not get called until the classes are first referenced - so if the super class methods are called that iterate through the class array of sub-classes before the sub-classes are all referenced, nothing is returned because no self.inherited calls have happened ... With class caching on the callbacks are called and life is happy. I have tried a number of solutions to this for development mode: * config.prepare_to did not work for this * eager_load directives did not work for this * config.after_intialize only works for initial load, fails to be called on reloead! * initializer did not work for this as only called once at startup So far the only one that works for both the initial load of development and after reload! is called looks like this (from our config/environments/development.rb). The problem of course with this code is that 1) it is horribly ugly and 2) it undoes the whole intent of the meta-programming when in development mode - which was to have sub-classes self-register so that we would not have to explicitly enumerate them and worry about forgetting to add one should we add another subclass :p. Any pointers / advice on how to not do it this way but have stuff work in dev like it does in other environments (works fine with no crazy code when class caching is true) much appreciated. - Max # XXX - workarounds for class_caching == false in development # mode. # # Sources for code fixes: # * http://blog.thefrontiergroup.com.au/2011/03/reloading-factory-girl-factories-in-the-rails-3-console/ # * http://guides.rubyonrails.org/configuring.html if Rails.env.development? # Bootstrap classes being referenced as we use meta-programming that # does not get called in development because class caching # is off. Merely accessing the classes by name triggers the # callbacks that otherwise get called immediately with class # caching on in non-development environments. def bootstrap_x_callbacks X1.nil? X2.nil? X3.nil? X4.nil? X5.nil? X6.nil? end # Run once on startup after Rails environment is all warmed up and # ready to rock. MyApp::Application.configure do config.after_initialize do bootstrap_x_callbacks end end # Schedule it to be called after every reload! ActionDispatch::Callbacks.after do bootstrap_x_callbacks end end -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung
2011-May-05 06:21 UTC
Re: Better way to force some classes to be eager loaded in development mode with Rails 3.0.5 and class caching off?
On May 5, 4:56 am, Max Schubert <max.schub...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> With class caching on the callbacks are called and life is happy. > > I have tried a number of solutions to this for development mode: > * config.prepare_to did not work for this > * eager_load directives did not work for this > * config.after_intialize only works for initial load, fails to be > called on reloead! > * initializer did not work for this as only called once at startup > > So far the only one that works for both the initial load of > development and after reload! is called looks like this (from our > config/environments/development.rb). > > The problem of course with this code is that 1) it is horribly ugly > and 2) it undoes the whole intent of the meta-programming when in > development mode - which was to have sub-classes self-register so > that we would not have to explicitly enumerate them and worry about > forgetting to add one should we add another subclass :p. > > Any pointers / advice on how to not do it this way but have stuff work > in dev like it does in other environments (works fine with no crazy > code when class caching is true) much appreciated.A slightly less horrible variant I''ve used in the past is class BaseX < ... end require_dependency ''sub1'' require_dependency ''sub2'' which is a little bit less horrible than having a random bootstrap_x method called in funny places but doesn''t solve the problem of being easy to forget to add to the list Fred> > - Max > > # XXX - workarounds for class_caching == false in development > # mode. > # > # Sources for code fixes: > # *http://blog.thefrontiergroup.com.au/2011/03/reloading-factory-girl-fa... > # *http://guides.rubyonrails.org/configuring.html > > if Rails.env.development? > > # Bootstrap classes being referenced as we use meta-programming that > # does not get called in development because class caching > # is off. Merely accessing the classes by name triggers the > # callbacks that otherwise get called immediately with class > # caching on in non-development environments. > def bootstrap_x_callbacks > X1.nil? > X2.nil? > X3.nil? > X4.nil? > X5.nil? > X6.nil? > end > > # Run once on startup after Rails environment is all warmed up and > # ready to rock. > MyApp::Application.configure do > config.after_initialize do > bootstrap_x_callbacks > end > end > > # Schedule it to be called after every reload! > ActionDispatch::Callbacks.after do > bootstrap_x_callbacks > end > > end-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Max Schubert
2011-May-05 16:50 UTC
Re: Re: Better way to force some classes to be eager loaded in development mode with Rails 3.0.5 and class caching off?
Frederick, On Thu, May 5, 2011 at 2:21 AM, Frederick Cheung <frederick.cheung-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> end > require_dependency ''sub1'' > require_dependency ''sub2'' > > which is a little bit less horrible than having a random bootstrap_x > method called in funny places but doesn''t solve the problem of being > easy to forget to add to the listwell, the bootstrap is not in a random place, it is in config/environments/development.rb, so the code only runs in development mode :) - and yes, neither is great: * Pollute base classes with knowledge of their sub-classes for every environment just to fix a development environment behavior * Add a bunch of custom code to development.rb to work around the same and not have to pollute production code Both create additional ''remember to'' tasks that undo a lot of the benefit the meta-programming is supposed to provide. - Max -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.