I have a SchoolDay class that represents a school day: it can tell you the date, the semester, the term, the week, and the day. It can generate a string like "Sem1 13A Fri". To store these objects in the database, I want them serialized as a string.
Here is my DataMapper custom type code. I've sort of scraped ideas from the code in dm-types because (disappointingly) there is no real documentation for creating custom types. Sorry it's long.
module DataMapper
class Property
class SchoolDay < DataMapper::Property::String
#load_as ::SchoolRecord::DomainObjects::SchoolDay
# Commented out: the 'load_as' method is not found
def load(value)
# Take a string from the database and load it. We need a calendar!
val = case value
when ::String then calendar.schoolday(value)
when ::SR::DO::SchoolDay then value
else
# fail
end
end
def dump(value)
# Store a SchoolDay value into the database as a string.
case value
when SR::DO::SchoolDay
sd = value
"Sem#{sd.semester} #{sd.weekstr} #{sd.day}"
when ::String
value
else
# fail
end
end
def typecast(value)
# I don't know what this is supposed to do -- that is, when and why it
# is called -- but I am aping the behaviour of the Regexp custom type,
# which, like this one, stores as a String and loads as something else.
load(value)
end
# private methods calendar() and error_message() omitted
end
end
end
This code works for reading from the (SQLite) database, but not for creating new rows. The error message is:
Schoolday must be of type String
The code that defines the DataMapper resource and tries to create the record is:
class LessonDescription
include DataMapper::Resource
property :id, Serial
property :schoolday, SchoolDay # "Sem1 3A Fri"
property :class_label, String # "10"
property :period, Integer # (0..6), 0 being before school
property :description, Text # "Completed yesterday's worksheet. hw:(4-07)"
end
# ...
ld = LessonDescription.create(
schoolday: @schoolday,
class_label: @class_label,
period: @period,
description: description
)
Here is the code for the Regexp datamapper type in the dm-types library. It's so simple!
module DataMapper
class Property
class Regexp < String
load_as ::Regexp # NOTE THIS LINE
def load(value)
::Regexp.new(value) unless value.nil?
end
def dump(value)
value.source unless value.nil?
end
def typecast(value)
load(value)
end
end
end
end
For some reason, I cannot use the load_as line in my code.
To summarise: I am trying to create a custom type that translates between a SchoolDay (domain object) and a String (database representation). The translation is easy, and I've copied the code structure primarily from the DataMapper Regexp type. But when I try to save a SchoolDay, it complains that I'm not giving it a string. Frustratingly, I can't use the "load_as" method that the built-in and custom types all use, even though I have the latest gem. I can't find the "load_as" method defined anywhere in the source code for DataMapper, either. But it's called!
Sorry for the ridiculous length. Any help would be greatly appreciated, as would a pointer to a guide for creating these things that I have somehow missed.
It seems that the current code of dm-types at github hasn't made it to any official release -- that's why load_as doesn't work in your example. But try to add this method:
module DataMapper
class Property
class SchoolDay < DataMapper::Property::String
def custom?
true
end
end
end
end
That's working here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With