hacking rails core classes

i think this has come up before, but i can't seem to find any references and googling isn't turning up much.

i have a set of modifications i've made to rails core classes which i find very useful, there are only a few, which i have in 'lib/railsext.rb', shown here

   Parked at Loopia

now i currently use

   load 'railsext.rb'

in app/controller/application.rb to merge these hacks into the rails core classes. i've found this is needed because of the way rails does reloading on each request - in otherwords some classes aren't fully baked until the code hits the ApplicationController.

now this works well, but it fails for

   ./script/console

in some respects.

my question is: if i'm hacking rails core classes like this is there a place i can do it, physically or logically, that will apply the hacks correctly regardless of whether the code is being loaded in a development request loop, from ./script/console, or however?

hopefully this question makes sense.

kind regards.

a @ http://codeforpeople.com/

Dear Ara,

Although this really is a question for rails-talk, not rails-core,
I'll just answer it here

If you want something loaded in your application that falls beyond the
scope of default Rails stuff (for example your Core ext) you should
load it in your environment.rb file. Just put it at the bottom. Or you can move the library from lib/ to config/initializers if you're
running Rails Edge / 2.1RC

Regards, Jan De Poorter

no that won't work, which is my whole point. loading code like that in environment.rb can cause issues because the classes get torn-down/built-up on the request loop. i've had issues with this before and had to read the source carefully to determine what can and cannot be done but i'm hacking an older rails app (1.2.3) and didn't want to go through that again. i know this question has come with respect to plugins as well and it's not simply the case that you can hack ActionController, ActiveRecord, or other rails classes at any point and have it work in all cases.

regards.

a @ http://codeforpeople.com/

just realized i could have been more specific:

if you put

class ApplicationController < ActionController::Base    hacks end

in lib/railsext and load that from environment.rb, and initializer, or a plugin, rails will fail to load ApplicationController in the request loop since it's not undefined and thus the const_missing code doesn't come into play. so the concrete issue is hacking ApplicationController in a modular way - in otherwords without dumping code into app/controllers/application.rb and avoiding hacking ActionController::Base itself (to avoid littering).

regards.

a @ http://codeforpeople.com/

Maybe I'm missing something here, but as far as I know this gets
solved in plugins with Class#include

You define your methods in a module, which you the include in
ApplicationController. That way const_missing gets called and
ApplicationController code gets loaded.

ApplicationController.send(:include, MyApplicationControllerHacks)

yup, and using ApplicationController.module_eval in a lib/* file has a similar effect. what i'm asking is what is the preferred/canonical method outside of plugins.

a @ http://codeforpeople.com/

just confirmed that the above will not work, at least not with ancient rails (1.2.3.). placing the single line

   ApplicationController.send :include, Module.new

in my lib/railsext.rb causes rails to blow up with

opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:422:in `remove_const': cannot remove Object::VERSION_MAJOR (NameError)          from /opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:422:in `send'          from /opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:422:in `remove_constant'          from /opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:368:in `new_constants_in'          from /opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:368:in `each'          from /opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:368:in `new_constants_in'          from /opt/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:495:in `require'          from /opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.3/bin/../lib/mongrel/rails.rb:147:in `rails'          from /opt/local/lib/ruby/gems/1.8/gems/mongrel-1.1.3/bin/mongrel_rails:113:in `cloaker_'           ... 19 levels...          from /opt/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/commands/server.rb:39          from /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'          from /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'          from ./script/server:3

on boot.

it's not that simple to hack ApplicationController, at least in older rails.

a @ http://codeforpeople.com/

Perhaps this might help? Auto-Patch Rails — err.the_blog

Jeff

it's not that simple to hack ApplicationController, at least in older rails.

Why are you munging ApplicationController? It's part of the application so it'll get reloaded every request in dev mode, and it's something you have control over. Basically you have two options:

1) Monkeypatch into ActionController::Base in a plugin / initializer

AC::Base isn't reloaded, so you'll be fine.

2) simply reference your module in ApplicationController's definition:

class ApplicationController < ActionController::Base   include InternetDrama end

Either of those should work fine.

Why are you munging ApplicationController? It's part of the application so it'll get reloaded every request in dev mode, and it's something you have control over.

simply because i want to both isolate and re-use the code. for this lib/railshacks.rb is preferable.

Basically you have two options:

1) Monkeypatch into ActionController::Base in a plugin / initializer

AC::Base isn't reloaded, so you'll be fine.

cool - this the route i ended up taking.

2) simply reference your module in ApplicationController's definition:

class ApplicationController < ActionController::Base include InternetDrama end

Either of those should work fine.

won't use that since the point is you have a single file for all my rails hacks and simple require it to put into effect, but that's nice.

thanks a bunch.

a @ http://codeforpeople.com/