DM-Types

Types are used by DataMapper to map ruby objects into values in the data-store on saving and to translate the values back into ruby objects when a resource is retrieved. The core library supplies several different types, providing mappings for most of the simple ruby objects as direct values in the data-store as well as the Object type which can store any Marshallable ruby object.

They’re intended to make the storage of ruby objects as transparent as possible, no matter what the ruby object is, or which data-store is used as the backend.

dm-types

In DM More there is the dm-types gem, which supplies several more types that map less common ruby classes to data-store values or take care of serializing them to text based formats.

Enum

The Enum type uses an Integer create a property which can take one of a number of symbolic values. A use for this might be bug status for an issue tracker or the protocol being used in a packet logging application.

1
2
3
4
5
6
7
8
9
10
11
12
class Issue
  include DataMapper::Resource

  property :status, Enum[ :new, :open, :closed, :invalid ], :default => :new
  # other properties ...
end

@i = Issue.new
@i.status
# => :new
@i.status = :open
# => :open

Flag

A Flag is similar to an Enum, though the property that is created can hold multiple symbol values at once. This could be used for recording which colours a product can be ordered in, or what extra features an account has enabled.

1
2
3
4
5
6
7
8
9
10
class Widget
  include DataMapper::Resource

  property :colours, Flag[ :red, :green, :blue, :heliotrope ]

  # other properties ...
end

@w = Widget.new
@w.colours = [ :red, :heliotrope ]

Object Mappings

These map objects into simple data-store primitives, then re-initialize as the ruby types

EpochTime
A ruby Time object stored in the data-store as an Integer – the number of seconds since the UNIX epoch.
URI
A ruby URI object, pre-parsed for use of methods such as #params or #uri, stored as a string in the data-store.
FilePath
Stored as a string in the data-store, FilePaths initialize Pathname objects, making it easy to perform various file operations on the file.
Regexp
A ruby regex, stored as a string.
IPAddress
Ruby IPAddr, stored as the string representation.
BCryptHash
Stored in the data-store as string representing the salt, hash and cost of a password using OpenBSD’s bcrypt algorithm, it offers an alternative to the more usual pair of hash and salt columns.

Serializers

These store values in the data-store using text based serialization formats. They work via calling dumping the object to the format on saving and parsing the text to reinitialize them on loading.

Writing Your Own

Writing your own custom type isn’t difficult. There are two (or perhaps three) methods to implement, as well as the selection of an appropriate primitive. All types are a class which should descend from DataMapper::Property::Object.

The Primitive

DataMapper offers several choices for a data-store primitive.

To assign a primitive to a type, either make the type descend from DataMapper::Property::(PrimitiveClass) or within the class definition, use primitive PrimitiveClass.

dump

A type’s dump(value) method is called when the object is saved to the data-store. It is responsible for mapping whatever is assigned to the property on to the primitive type. For example, the EpochTime Type saves an integer directly to the data-store, or calls #to_i if a Time object is passed to it.

load

The load(value) method is called when the property is retrieved from the data-store. It takes the primitive value and initializes a ruby object from it. For example, the Json type performs JSON.parse(value) to convert the json string back into appropriate ruby.

typecast_to_primitive

Typecasting is provided by the types typecast_to_primitive(value) method, which tries to coerce whatever value the property has into an appropriate type. A type doesn’t have to provide a typecast but it can be useful, for example to allow the string ‘2008-09-06’ to be converted to a ruby Date without having to reload the model.

Examples

For examples of the types, the best place to look is dm-types on github.