onsdag, september 06, 2006

ActiveRecord-JDBC 0.2.0

Earlier today I finally released version 0.2.0 of ActiveRecord-JDBC. Since it contains fairly big changes I decided to bump the version number a bit, from 0.0.1 to 0.2.0. This blog entry will first describe what's new and cool about this release, and then show how to get started with this adapter inside Rails.

What's new
Of course, to warrant a new release, there's got to be some good stuff in it, and I can really say I'm proud of the funcionality included in this package. I feel that the first release was much proof-of-concept, and to make it easy for people to follow along in the Camping tutorial. But with this release, ActiveRecord-JDBC is definitely an option for a real project.

ActiveRecord-JDBC (AR-JDBC from now on) ships with support for 8 databases, including migrations. Adding support for more is often very trivial and we hope to very soon have support for most major databases. What works right now is:
  • MySQL
  • PostgreSQL
  • Oracle
  • Microsoft SQL Server (except for change_column_default)
  • DB2 (except change_column, change_column_default, rename_column, remove_column,
    add_index, remove_index and rename_table)
  • Derby (except change_column, change_column_default, remove_column, rename_column)
  • FireBird (except change_column_default and rename_column)
The exceptions in this list will probably not be fixed, since there is no support in the database for this functionality. Of course, some of it could be faked by expensive copy-table operations, but this seem to be detrimental since it often doesn't work for sequences and identity columns. We felt it was better to just don't support renaming tables in those drivers.

Putting JDBC on Rails
Now, I will detail how to create a basic Rails application using JRuby and AR-JDBC. I assume you have a working JRuby installation, and have installed Rails. Since I have rails and gem in my global path from regular Ruby, I have added symlinks in $JRUBY_HOME/bin to make it easier using these commands. Specifically, I will use jem for gem, jails for rails and jake for rake. This makes the command lines very much shorter indeed.

The first step is to install the AR-JDBC gem: (we don't generate rdoc and ri since these are still expensive operations in JRuby)
jem install -y ActiveRecord-JDBC --no-ri --no-rdoc
After this operation has completed, the next step is to create our rails-application:
jails test_arj
This will take a while and generate the usual files. Now, to actually make Rails use the JDBC-connector, we need to change environment.rb to load our jdbc_adapter. There's a thread on the rails-core-list about making this step unnecessary, but right now it's needed. Anyway, modify the head of the file to look like this:
require File.join(File.dirname(__FILE__), 'boot')
require 'jdbc_adapter'
Rails::Initializer.run do |config|
that is, add a require for the jdbc adapter. The next step is to configure your database. I will the Derby embedded driver for this, but the concept is the same; just change the adapter name, add driver, url and possibly username and password. This is the configuration any JDBC driver takes so it shouldn't come as a surprise for Java developers. Make sure the driver is on your CLASSPATH before running anything, though. My development-database specification looks like this:
adapter: jdbc
driver: org.apache.derby.jdbc.EmbeddedDriver

url: jdbc:derby:test_arjdbc;create=true

and you see here that there isn't anything strange going on, we just configure the JDBC driver with the same parameters as usual.

From now on, the operations are the same as when creating a regular Rails application. First, create the model:
jruby script/generate model Product
and then edit db/migrate/001_create_products.rb by adding this:
t.column :title, :string
t.column :description, :text
t.column :image_url, :string
t.column :price, :float
Nothing strange. When this is done, we can create our data:
jake db:migrate
which, since we've chosen to use Derby, will create some database files in the current directory. This is what I want for now. After this step, some scaffolding is in place:
jruby script/generate scaffold product
You will notice we have to use jruby explicitly for some scripts. This is because the shebang doesn't get set correctly for these files.

After this step I copied my development configuration to the production configuration in the database and started webrick in production mode (since it's much faster right now):
jruby script/server -e production
Now you should be able to visit http://localhost:3000/products and going wild crudding your products.

... And the rest? There is nothing more. From here on, it's a regular Rails application, just with the added benefit of all the Java resources in the world available to you.

4 kommentarer:

Anonym sa...

Ola, thanks for a fine write-up. Nice take on naming the Rails tooling, "jem" was a favorite.

Congratulations on the AR-JDBC release. A true enabler.

Anonym sa...

Thank you for your valuable work.
What might cause the following error?

C:\jruby-trunk\test_arj>jruby script/generate model product
org.jvyaml.ScannerImpl.fetchValue(ScannerImpl.java:508): org.jvyaml.ScannerExcep
tion: ScannerException null we had this mapping values are not allowed here (Nat
from org.jvyaml.ScannerImpl.fetchMoreTokens(ScannerImpl.java:329)
from org.jvyaml.ScannerImpl.peekToken(ScannerImpl.java:158)
from org.jvyaml.ParserImpl$20.produce(ParserImpl.java:369)
from org.jvyaml.ParserImpl.parseStreamNext(ParserImpl.java:773)
from org.jvyaml.ParserImpl.peekEvent(ParserImpl.java:724)
from org.jvyaml.ComposerImpl.composeNode(ComposerImpl.java:162)
from org.jvyaml.ComposerImpl.composeDocument(ComposerImpl.java:95)
from org.jvyaml.ComposerImpl.getNode(ComposerImpl.java:71)
... 296 levels...
from C:/jruby-trunk/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
:in `require'
from C:/jruby-trunk/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
:in `require'
from script/generate:2
Complete Java stackTrace
mapping values are not allowed here

Ola Bini sa...

Hi anynoumous.

I'm pretty certain that the error you're experiencing is due to a problem with your database.yml. There is something in the YAML format that isn't correct. Maybe you have a tab somewhere for indentation?

TechnoSqueek sa...

Great work! I was able to connect my Intel Mac to my Oracle Express database using the JDBC drivers that are installed with the InstantClient. This is very cool!