DataMapper without a database
George Malamidis, May 29th, 2008DataMapper is fast becoming a credible contender in the Ruby ORM field. The first - and only at this early stage - thing that temporarily disappointed me was the following scenario.
class Foo include DataMapper::Resource property :id, Integer, :serial => true property :title, String end
Running this produces ArgumentError: Unknown adapter name: default, suggesting that a database connection needs to be setup in order to use any objects that include the DataMapper::Resource module. This is something I would rather not have to do for my dependency neutral test suite, in which all calls to ORM objects are simulated using mocks.
I soon realized that DataMapper doesn’t require a database connection to be present, but needs to know which adapter to use. If we’re not interested in interacting with the database, using DataMapper::Adapters::AbstractAdapter does the trick.
DataMapper.setup(:default, "abstract::") class Foo include DataMapper::Resource property :id, Integer, :serial => true property :title, String end Foo.new(:title => "metal").title # => "metal"

May 30th, 2008 at 6:09 am
Yeah, that’s annoying. I’ll try to fix it up. Time is a problem.
So the reason this is happening is because the NamingConventions are per-adapter. So one database can have one set of conventions, another can have a different set.
So, to inflect the #storage_name, we need a handle on the Adapter.
Obviously there’s nothing in the above code that actually needs the #storage_name at that point. So we just need to make it a little lazier, and you won’t have this issue. As you discovered, a valid connection isn’t necessary. Just a handle that responds to #storage_naming_convention and #field_naming_convention.
Thanks for the kind words.
On the plus-side, DM is unofficially-officially supported by my employer, Wieck Media, and I’ll be dedicating some more team hours to patching up some of the remaining issues. Expect a 0.9.2 release next Friday if not sooner.
June 6th, 2008 at 5:35 am
If you don’t mind a little db dirtiness (or cleanness depending on your perspective) you can try in memory sqlite3 adapter: DataMapper.setup(:default, “sqlite3::memory:”). You can keeping mocking your way through w/ occasional SQL magics. You’ll probably want to do DataMapper.auto_migrate! as well.
June 9th, 2008 at 10:32 pm
DataMapper looks like a much better solution that AR::B, but again we are stuck with objects that require a database to exist.
I’ve been using the following which almost helped:
module DataMapper::Resource::ClassMethods
def find_or_create search_opts, create_opts
create create_opts
end
def create create_opts
new create_opts
end
end
But at some point it fails in AbstractAdapter#read_set append to an association proxy.
Also many_to_many does not work.
Maybe its time to create a NullAdapter so people can write unit test and use models independently of a database? For example: serialize object graphs to a client that should not have access to a DB.
When is somebody going to create a truly orthogonal ORM for Ruby, without load-time dependencies, so we can stop modeling databases and start modeling objects with some possibility of reuse?
I’m so ready to ditch AR::Base for the right solution…
June 10th, 2008 at 4:55 am
Kurt, it would be relatively easy to write a DataMapper Adapter that uses in-memory storage rather than rely on an external dependency like a database.
FYI the AbstractAdapter API is getting a bit of an overhaul based on our usage patterns. It should be more consistent and easier for Adapter authors to write new adapters. Work is progressing on it now and it should be ready and tested within the next week or so. The reason I say this is if you decide to write such an adapter you’ll want to join us on IRC for the full details.