Ruby on Rails
AlternativesToActiveRecord

Add information regarding alternative data models to ActiveRecord here.

ActiveRelation?

I love Rails. Hopefully in a few years time we’ll look at it as the first stage of a breakthrough in web development, leaving all that irritating J2EE crap behind and allowing people to use powerful languages and functional programming techniques to do everyday web-based database work.

I do have a few beefs with ActiveRecord though. While it is very useful, I find myself frustrated by some of its limitations. It can’t deal with multi-column primary keys, infact (as I recall) it requires that the primary key is a single integer auto_increment column. It won’t auto-detect foreign keys, and when you want to do complex queries with lots of joins you end up having to pass it bits of join SQL as text.

If anyone’s interested, particularly any of the Rails developers, I am actually working on an alternative to ActiveRecord called ActiveRelation?, which aims to provide full(er) support for the relational model within the confines of a Ruby-based ORM tool. It’s geared very much towards providing a clean Ruby-style syntax for querying and working with a relational database, rather than being a database-backed persistance mechanism for existing Objects. (ActiveRecord can’t seem to make up its mind which of these two it wants to be, although it does swing more towards the former).

My ActiveRelation? will inspect the database to find all relations with their primary keys and foreign keys, and places no restrictions on your DB schema. It also has a powerful syntax-building system for the relational algebra, allowing you to build up syntax trees for arbitrary queries, which can then be used as iterators to fetch the results in friendly ORM-style object wrappers. The ORM features are built over the top of the relational algebra stuff, rather than joins and so on being added as an afterthought to the ORM code.

It can often ‘guess’ how to join tables given what it knows about foreign keys, so you can do things like this:

Location.select(Location.name == 'London').join(Artist).join(Label).    \
    project(Label).each {|label| puts label.name }

To show all labels who’ve signed london artists.

It also provides friendly get and set methods for foreign keys automatically, like so:

a = Artist.get_by_primary_key(1234)
puts a.link.url
puts a.label.location.name
a.link = Link.new! :url => 'http://foo/', :name => 'Foo'

And what’s more, the relevant associated row objects are cached automatically when the object is the result of a query with joins.

Joins can also be made to rows themselves – eg:

me = User.get_by_primary_key(1)
me.join(UserRole).join(Role).project(Role).each do |role|
  puts "Matthew does #{role.name}" 
end
# actually a shortcut for
# User.select(User.userid == me.userid).join(Role).join(...

It also comes with some helper methods which let you tell it about many-to-many relationships and tree structures, rather like ActiveRecord. So if you tell it

class User
  many_to_many UserRole, Role
end

you can do

me.roles.each {|role| puts role.name}

as a shortcut for the above. None of the above is making any assumptions about what names you’ve given to key columns, it’s guessing the keys to use in the joins from it’s info about foreign keys. If you don’t like its guess (say you have two foreign keys to the same table) you can tell it explicitly.

Neat huh? Only disadvantage is that it currently only works with MySQL and the InnoDB storage engine. But that could easily be changed if I had the time. It could also benefit from a bit of optimisation and clean-up. Let me know if you’re interested in trying it out though, I intend to GPL it at some stage. Also if anyone would be interested in helping me integrate this fully into Rails as an alternative to ActiveRecord, or has any other thoughts on the matter, I’d definitely be interested.

-matt at drownedinsound dot ckom

Anyone looking at creating a more ‘featured’ ORM that allows you to map objects directly to stored procs and views?
I only want access to the db via sp and views (no direct access to tables). That would be ideal

-Lal thelal at iname dot dot com

There is also another library called Og that may be an alternative to ActiveRecord. This library is used by the Nitro framework, which is an alternative to Rails.

- ykoehler

ActiveRecord maps objects to views out of box. However, depending on your RDBMS, you may need additional DDL to tell the DB that view is updatable in case you want to save objects to it.
As for stored procedure to object mapping – the idea of stored procedures is to encapsulate behaviour inside the DB, and ActiveRecord does precisely the opposite – it encapsulates behaviour outside DB. However, it does not stop you from calling stored procs:

ActiveRecord::Base.connection.execute("sp_call()")

or, if you still want something in return,

ActiveRecord::Base.connection.select_all("sp_call()")

- sava.chankov@gmail.com