Rails 2.0 made writing your own ActiveRecord adapters easier. Combine
that with JDBC and you have some really nice tools for creating data
driven ruby applications working against any number of databases.
So, How Do I Write One?
Like a lot of things in the Ruby and Rails world, once you understand
the conventions, everything else is easy. So much so that, once you
know what you are looking for, writing an adapter is about copying the
patterns that have already been laid out in the other adapters.
The key steps for creating an adapter are:
- create a new lib/jdbc_adapter/jdbc_<adaptername>.rb
- update lib/active_record/connection_adapters/jdbc_adapter_spec.rb to
- create a new test/<adaptername>_simple_test.rb and an associated
- add test rake task to the Rakefile.
(these were basically stolen from an email on the JRuby Users mailing list).
What Goes Where?
For the most part, you can figure out everything else you need to know
by reading the code. If you aren’t sure how to do something, there’s
probably already an example of it in the code somewhere.
Here are some things I think I’ve figured out:
- Most of the magic happens in the
lib/jdbc_adapter/jdbc_<adaptername>.rb file. The rest of these
points describe points of interest in that file.
- ::JdbcSpec::ActiveRecordExtensions is where you put the connection
method, <adaptername>_connection. This is what Rails will call when
someone sets the adapter name to <adaptername>. You can use this to
turn Rails flavored config hashes into nasty JDBC URLs. Users will
- Create a ::JdbcSpec::<AdapterName> module. Make sure you follow the
conventions for self.column_selector and
self.adapter_selector. There’s no reason not to.
- Lots of crazy stuff happens in the ::JdbcSpec::<AdapterName>
module. Write a custom create_table method. Rewrite “LIMIT 1″
queries for dialects that don’t support the LIMIT keyword. Support
migration behaviors that aren’t natively supported by the
database. Many more examples exist.
- Create a ::JdbcSpec::<AdapterName>::Column module. This is where
individual field customization happens. You can customize quoting
and unquoting of fields and column names. You can cast special types
(like bit to boolean). You can modify types on the fly.
Eh, probably. I can’t think of anything else that you necessarily need
to know. I suppose you could do all of your modules in Java as part of
a Ruby Service. If your database driver has a friendly enough license,
you could distribute that as its own gem. This simplifies distribution
and installation for end users. I haven’t tried that yet, but it looks
simple enough. Leave a comment if can think of something I missed.