A while ago, I asked if it was possible to use something like MappedEnum
and have some sensible values inserted into the database instead of
integers.
I got the feeling this was not the case, so I've created MappedEnumString
(attached) which maps Enumerations into string values.
Example:
object TestTypes extends Enumeration {
val Unknown = new Val(0,"??")
val Item1 = new Val("XX")
val Item2 = new Val("YY")
}
object test extends MappedEnumString(this, TestTypes, 2)
This will store the values, ??, XX or YY in the db. For display
purposes, it will by default lookup the resource values TestTypes.??,
TestTypes.XX, TestTypes.YY
You can also calculate the displayed values:
object test2 extends MappedEnumString(this, TestTypes, 2) {
override def _valueToDisplayString(v:Enumeration#Value) = v match {
case TestTypes.Item1 => "Item1Display"
case TestTypes.Item2 => "Item2Display"
case _ => "Unknown x ItemDisplay"
}
}
I'm by no means a Scala/Lift expert so I may have overlooked stuff, so
feel free to comment :-)
/Jeppe
Good question :-) I'm still using CRUDify generated views while
prototyping, but will probably need some more sophisticated layouts at
some point. Don't yet know if the display value will come from the
mapper object or the underlying enum.
> I have a rough implementation called EnumWithDescription, that wraps (not extends) an Enumeration
> and provides a description method on the enumeration value without using an implicit. I'm wondering
> if it might be useful to combine your approach and mine?
Sure. It might also be possible to make the original MappedEnum a bit
more flexible instead (as Derek suggested earlier). My class is
basically just a copy with very few modifications to handle the db
value. I just haven't got the Scala knowledge yet to easily see how
the interface should be and I needed to nail the db schema :-)
/Jeppe
/Jeppe
[...]
> No this isn't what I'm suggesting, I don't think MappedEnum should be made
> flexible.
I know this wasn't your suggestion, but any reason not to make
MappedEnum flexible (if possible and backwards compatibility could be
maintained) ?
> I was thinking perhaps your class could work with EnumWithDescription
> as shown below, which extends Enumeration#Values to include a
> description.
This should be simple, but see below
> trait ValueWithDescription {
> def description: String
> def name: String
> }
> abstract class EnumWithDescription {
> type Value = enum.Value with ValueWithDescription
>
> private var _values: List[Value] = Nil
> def values = _values
>
> // possibly not a good idea using this directly
> val enum = new Enumeration {
> def Value(inName: String, inDescription: String): Value with
> ValueWithDescription = {
> new Val(nextId, inName) with ValueWithDescription {
> def description = inDescription
> def name = inName
> }
> }
> }
> def Value(name: String, description: String): Value = {
> val value = enum.Value(name, description)
> _values = _values ::: List(value) // build in order
> value
> }
> def Value(name: String): Value = Value(name, name)
> def valueOf(name: String) = values find (_.name == name)
> def nameDescriptionList = values map(x => (x.name, x.description) )
> }
At first I didn't understand why you don't just extend Enumeration like
this:
abstract class EnumWithDescription extends Enumeration {
def Value(inName: String, inDescription: String): Value with ValueWithDescription = {
new Val(nextId, inName) with ValueWithDescription {
def description = inDescription
def name = inName
}
}
}
but figure you would then have to cast all the values to
ValueWithDescription. It seems Enumeration miss a type parameter to
describe the types of Values in cases like this. Hmmm I see Enumerations
have changed for 2.8 so maybe this is not impossible....
Back to the mapping. The way I see all these different solutions is:
1) We need to define Enumerations to get nice handling of predefined
constants
2) The enumeration values need to be mapped to a database value (numeric
or string)
3) The enumeration values need to be mapped to a display value (from
code our property files)
If the MappedEnum was parameterized on how to achieve 2+3 it seem all
possibilities are open. If MappedEnum worked with ValueWithDescription
values instead of Enumeration#Value, it might? be possible to define an
implicit conversion from Enumeration#Value to ValueWithDescription....
I don't have much time in the days that are coming but will try to think
of a solution to this. Input is welcome :-)
/Jeppe