Improve load speed from the database by 1000% (and fix specs and add Rails 4 support)

The tl;dr here is that MongoMapper is doing some really ugly things - notably, letting the Dirty plugin get its hands on content as it's being loaded from the DB, and performing #extends on instance variables, which is torching the entire Ruby method cache on a regular basis. This PR fixes this.

First, let's benchmark!

I was interested in comparing Mongoid with MongoMapper, and was rather dismayed to find how abysmally MM was performing. It's worth noting that Mongoid uses the Moped driver, while MM uses the 10gen Mongo driver (which, IMO, is something of a mess; part of the blame is due there).

The benchmark is here: https://github.com/cheald/mongo_odm_bench

This comparison is MongoMapper 0.12.0 vs Mongoid 3.1.4

           user     system      total        real
    MongoMapper Insert  0.480000   0.040000   0.520000 (  0.542837)
        Mongoid Insert  0.530000   0.040000   0.570000 (  0.574484)
        
           user     system      total        real
    MongoMapper Read 150        batches of 1           0.170000   0.010000   0.180000 (  0.212139)
        Mongoid Read 150        batches of 1           0.050000   0.010000   0.060000 (  0.066210)
    MongoMapper Read 3750       batches of 25          1.700000   0.180000   1.880000 (  1.937555)
        Mongoid Read 3750       batches of 25          0.180000   0.020000   0.200000 (  0.211497)
    MongoMapper Read 15000      batches of 100         6.540000   0.620000   7.160000 (  7.263680)
        Mongoid Read 15000      batches of 100         0.620000   0.050000   0.670000 (  0.704031)
    MongoMapper Read 75000      batches of 500        32.200000   2.960000  35.160000 ( 35.474875)
        Mongoid Read 75000      batches of 500         2.930000   0.280000   3.210000 (  3.277081)
    MongoMapper Read 150000     batches of 1000       64.250000   5.950000  70.200000 ( 70.786035)
        Mongoid Read 150000     batches of 1000        5.810000   0.580000   6.390000 (  6.499160)

Now, with my patches:

           user     system      total        real
    MongoMapper Insert  0.740000   0.080000   0.820000 (  1.205486)
        Mongoid Insert  0.530000   0.040000   0.570000 (  0.580322)
           user     system      total        real
    MongoMapper Read 150        batches of 1           0.050000   0.000000   0.050000 (  0.068624)
        Mongoid Read 150        batches of 1           0.060000   0.010000   0.070000 (  0.070675)
    MongoMapper Read 3750       batches of 25          0.190000   0.030000   0.220000 (  0.234519)
        Mongoid Read 3750       batches of 25          0.180000   0.020000   0.200000 (  0.215139)
    MongoMapper Read 15000      batches of 100         0.600000   0.110000   0.710000 (  0.745613)
        Mongoid Read 15000      batches of 100         0.600000   0.060000   0.660000 (  0.692381)
    MongoMapper Read 75000      batches of 500         2.960000   0.440000   3.400000 (  3.471220)
        Mongoid Read 75000      batches of 500         2.890000   0.280000   3.170000 (  3.227801)
    MongoMapper Read 150000     batches of 1000        5.830000   0.950000   6.780000 (  6.896435)
        Mongoid Read 150000     batches of 1000        5.710000   0.550000   6.260000 (  6.375876)

The time to read 15k records was reduced from 70.7 seconds to 6.89 seconds, an improvement of 1026%. I'm pretty sure that the difference in insert time is due to the updated "safe" parameter, which I didn't explicitly set in the 0.12.0 config.

[Edit: And here's for the current repo head, which is much better, but I've managed to ~triple performance even over that!)

           user     system      total        real
    MongoMapper Insert  0.720000   0.080000   0.800000 (  1.222013)
        Mongoid Insert  0.520000   0.040000   0.560000 (  0.557910)
           user     system      total        real
    MongoMapper Read 150        batches of 1           0.080000   0.010000   0.090000 (  0.100922)
        Mongoid Read 150        batches of 1           0.050000   0.000000   0.050000 (  0.065750)
    MongoMapper Read 3750       batches of 25          0.580000   0.080000   0.660000 (  0.679814)
        Mongoid Read 3750       batches of 25          0.180000   0.010000   0.190000 (  0.221572)
    MongoMapper Read 15000      batches of 100         2.100000   0.240000   2.340000 (  2.381593)
        Mongoid Read 15000      batches of 100         0.620000   0.080000   0.700000 (  0.718032)
    MongoMapper Read 75000      batches of 500        10.160000   1.140000  11.300000 ( 11.426766)
        Mongoid Read 75000      batches of 500         2.920000   0.320000   3.240000 (  3.302835)
    MongoMapper Read 150000     batches of 1000       20.120000   2.350000  22.470000 ( 22.671705)
        Mongoid Read 150000     batches of 1000        5.860000   0.550000   6.410000 (  6.525847)

* The big change here is that when loading from the database, we use an `#internal_write_key` method that isn't eligible for plugins to overwrite. Previously, things like the Dirty plugin's `#write_key` would be invoked when loading from the DB, which in turn invoked read_key and a whole other chain of things. This massively slowed down read
speeds.
* In two places, runtime instances were being `#extend`'d. **This wipes the Ruby method cache** and slows down the entire application. Those two instances have been refactored out.
* Other changes have been made to improve `#internal_write_key`. First off, uncast values are now stored in write (by the app, not the DB), and only then from the Rails plugin, as that's the functionality that is concerned with uncast values. It's now a simple hash lookup rather than being a whole mess of ivars.
* `Keys#keys` now copies the class.keys to an ivar when it's used. This method is used very frequently, and avoiding the extra function call has substantial benefit when you start adding it up.
* `is_a?` was replaced with `instance_of?` in a number of places; this is faster when you want to compare types directly, rather than the inheritance hierarchiy.
* We're testing !foo rather than foo.nil? in a number of places for similar reasons.
* In a few places, ivars were used rather than their prettier accessors. Avoiding the function call does add up when you're calling it hundreds of thousands of times.
* Several tests which were too brittle have been fixed.

I'm quite certain that there are a number of other places to make improvements, but I'm pretty happy with a 10x improvement for an evening's worth of hacking.