How I've Monkeypatched AR

To bump this thread...

http://www.continuousthinking.com/2007/3/15/refactoring-activerecord-base

Since AR can change so rapidly, I am planning on working on the majority my patch over the weekend so I can propose changes before to much else changes. After the first patch is done I will submit it to those here on core, to receive some feedback, suggestions and criticism, and also to give me some time to reflect. After that I'm planning on revising the patch one or two more times before submitting for a final submission to AR itself.

I'm game for remote pairing as well as I believe two heads are better then one, and that it will be most crucial to keep these changes as simple and as clean as possible. Any core dev or AR hacker interested?

Zach

Sorry for the late response - missed this thread until now.

In my hacking with AR, there have been two big frustrations:

1. A lot of things are done via metaprogramatically rewriting classes, as opposed to breaking things down into an object model. Example: The DSL for validations is wonderful. There have been a lot of requests to make it depend on different contexts (see ContextualValidation ). I tried doing this, but gave up - if you look at the validation DSL methods, they rewrite the class. It's quite hard to decompose them or modify them.

A simpler way would be to have a @validations collection in each AR class (or perhaps each instance could have their own). The DSL would add to the collection, and valid? would check them all. Then it would be easy to:

* Use the DSL to make validators for different contexts * Use the DSL and non ActiveRecord objects (frequently requested, also) * Add validators programatically (for some of those hypermodern admin interfaces)

2. Handling SQL as strings, as opposed to query + params. This is the big one that all plug in authors seem to complain about. It makes it really hard to get down deep into AR (and can make porting things harder as well).

Besides the plugin benefit, handling the SQL as a query + params has 2 *huge* benefits: A. We can, similar to DBI, first create the query, and then use it with new params. According to Stefan Kaes ( A Look at Common Performance Problems in Rails ) , AR spends more time feeding the db the SQL than the DB takes to run it! B. BLOBs. Passing them into the string makes everything slow and ugly. I would guess a 10x speed improvement on large BLOBs.

On this point, what I'd like to see - ideally - is using something like DBI at the base level, with AR building on top of it. DBI lacks some functionality that AR has - but that can be added into DBI just as easily as AR. This would make porting AR to new databases easier, and would also allow cross polination between Rails' users and the general Ruby community at large (who may want to access their db's without AR). (Note: if there are other problems with DBI that I'm not aware of - we could still use something similar - the point is to have 1 layer for querying, reflecting on, and talking to the DB, and another layer for AR's magic)

On this point, what I'd like to see - ideally - is using something like DBI at the base level, with AR building on top of it.

I presume you are referring to:

http://rubyforge.org/projects/ruby-dbi/

Anyone have experience using it?

-- Ernie P.

In my plugin for specifying custom finder SQL for eager-loading of associations ( http://rubyforge.org/projects/eagerfindersql ), I needed to work hard to avoid not completely re-implementing each associated class. I needed to pass extra options in ActiveRecord::Associations::find_with_assocations down into private subclasses: ActiveRecord::Associations::JoinDependency and JoinBase.

To keep from having to redefine the initializer for each of these classes, I ended up using a thread variable to hold the mapping data structures needed to assign results from the query to different associations. Not an ideal solution, but it did solve the problem with minimal overriding of methods within these classes.

Gregg Kellogg www.kellogg-assoc.com