# The problems with Types in DataMapper

Over the past few months, I've written many adapters for DataMapper,
interfacing with a wide variety of data stores. [A ReST-flavored
one][dm-ssbe-adapter], [TokyoTyrant][tokyotyrant], and some internal
ones that
I can't share. It's my second or third iteration on each, and I've
been
changing the Adapter API in dm-core as a result of my experiences.
However,
they're still not as polished or featureful as I'd like, due to still
more
deficiencies in the API. The most significant of these is the current
types
implementation.

## Can't detect the type of a property

Currently, its extremely difficult to inspect the type of a property.
Consider
the following code:

    require 'dm-core'

    DataMapper.setup(:default,
                     :adapter => :in_memory)
    class Person
      include DataMapper::Resource

      property :id, Serial
      property :name, String

      property :created_at, DateTime
    end

    Person.properties.each do |p|
      case p.type
        when String then puts p.inspect
      end
    end

    # no output

This is because property.type === String returns false, because its
not really
a String, is a DM::Types::String. We could add #===, but that would
require
everyone implementing a custom type to do the same.

## Non-adapter specific type de/serialization

The "native" dm types currently do no serialization at all. In most of
my
adapters, I serialize Time-like properties as [iso8601] times. I like
it
because it is concise, and human-readable. Currently, though, dm-core
doesn't
do any typecasting at all on native types. So when I save a DateTime
to the
  data store, then load it again, I get it back as a string, not a
DateTime. My
  preferred way would be to use a case statement, to detect if I'm
loading a
  DateTime, and parse it approprietly, but that obviously doesn't
work. It's
  also far from ideal.

## Writing new types is non-trivial.

Currently, anything used as a type has to to written as a DM::Type
subclass.
You also need to set a primitive, and methods for serializing/
deserialize the
value into something understandable by SQL. This is less than ideal
for writing
new types, and also completely unworkable for non-SQL adapter.

# Proposal

I have started a branch to address some of these issues: [paul/dm-core/
types].
Some of the important features:

There's no such thing as a datamapper Types. The type attribute of a
property
is just a normal ruby class, and can be absolutely anything. This
makes
ruby-native adapters, such as in-mem and yaml, trivialy easy to do,
because no
typecasting need be done. Writing new "types" is also easy, you just
make a
class.

The "custom" type is just a regular type, that sets some default
options on the
Property when its used. An example of the Serial type:

    class Serial < Integer
      include DataMapper::Type

      default_options[:key]    = true
      default_options[:serial] = true
    end

Just include the DataMapper::Type to get the `default_options` method,
and set
the Property options you want. When you do `property :foo, Serial`,
those
options will be automatically set on the property.

Types are just the ruby class, which means that case statements and
`===` work
just like normal.

De/Serialization now become part of the responsibilty of the adapters.
I would
like to have a mechanism where a type would be registered with the
adapter.
Some examples of how that might be accomplished:

    class PostgresqlAdapter
      add_save(UUID) { |val| val.to_s }
      add_load(UUID) { |val| UUID.parse(val) }

    end

This would allow custom, adapter-specific types to be implemented
easily.

# Conclusion

DataMapper, as it stands now, is completely unworkable for writing
adapters
that are non-trivial, and depart to far from the RDBMS mindset. Fixing
and
simplifing types will be a huge step in making it more plausable. My
proposal
is a pretty major departure from what we have now, but we get to
greatly
simplify some of the more complex code in DataMapper but doing this.
Dan Kubb
has is own ideas on how Types should be handled, but I'm not sure
they're any
better from the point-of-view of an adapter author. I hope to get some
debate
going over which is better, because I need better features in my
adapters soon.



[dm-ssbe-adapter]: http://github.com/absperf/dm-ssbe-adapter
[tokyotyrant]: http://github.com/paul/dm-tokyotyrant-adapter
[iso8601]: http://en.wikipedia.org/wiki/ISO_8601

[paul/dm-core/types]:
http://github.com/paul/dm-core/commit/9ebd915801af439dce66430b9d2d64433861e778


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"DataMapper" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/datamapper?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to