Form validation: notice on conversion failure?

119 views
Skip to first unread message

Michael Strecke

unread,
Sep 8, 2010, 7:57:45 PM9/8/10
to lif...@googlegroups.com
When a form is submitted and for example a date field contains letters,
the conversion in the respective field seems to fail silently, and the
original value is not changed.

I wonder, if there is a (standard) way to inform the user of that event.

If I understand correctly, the form validation functions are only called
when a value has been successfully converted.


Mike

Derek Chen-Becker

unread,
Sep 10, 2010, 1:51:26 PM9/10/10
to lif...@googlegroups.com
There's no direct support for this in Mapper, but I do think that it's something that would be nice to add, perhaps through a handleParseFailure def on MappedField that could be overridden with your own code. Right now you can achieve this by overriding setFromAny within a trait like:

trait MappedDateParseErrorHandler[T] {
  self : MappedDate[T] =>

  def proxyParse(s : String) : Date = {
    LiftRules.dateTimeConverter().parseDate(s) match {
      case f @ Failure(...) => handleDateParseError(f)
      case e @ Empty => handleDateParseError(e ?~ "Unknown parse failure")
      case Full(date) => this.set(date)
    }
    // Return whatever the current value is
    this.is
  }

  def handleDateParseError(error : Failure) : Unit // Implement this in your field
   
  override def setFromAny(f : Any) : Date = f match {
    case s : String => proxyParse(s)
    case (s : String) :: _ => proxyParse(s)
    case other => super.setFromAny(f)
  }
}

And then you should be able to mix it in like:

object birthday extends MappedDate[Person] with mappedDateParseErrorHandler[Person] {
  def handleDateParseError(error : Failure) { ... }
}

This code is off the top of my head, so there may be some errors in it, but that's the general idea for now. Please open a ticket for enhanced functionality on Mapper fields to make this standard and I'll work on it.

Derek
   


--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.


Michael Strecke

unread,
Sep 12, 2010, 9:19:15 AM9/12/10
to lif...@googlegroups.com
Thank you for your response and the sample code.

Unfortunately the code did not compile. It took some time, and some
re-reading of self-types, and with a few minor changes, I got it to work.

As for opening a ticket for enhanced functionality on Mapper fields, I'm
not able (or perhaps allowed) to create one.

Here is the modified version:


trait MappedDateParseErrorHandler[T <: Mapper[T]] {
self : MappedDate[T] =>

def proxyParse(s : String) : Date = {
LiftRules.dateTimeConverter().parseDate(s) match {

case f @ Failure(_,_,_) => handleDateParseError(f)


case e @ Empty => handleDateParseError(e ?~ "Unknown parse failure")
case Full(date) => this.set(date)
}
// Return whatever the current value is
this.is
}

def handleDateParseError(error : Failure) : Unit // Implement this in
your field

override def setFromAny(f : Any) : Date = f match {
case s : String => proxyParse(s)
case (s : String) :: _ => proxyParse(s)

case other => this.setFromAny(f)
}
}

...

class Person extends LongKeyedMapper[Person] with IdPK {
def getSingleton = Person
object birthday extends MappedDate(this) with
MappedDateParseErrorHandler[Person] {
def handleDateParseError(error : Failure) = {
...
}
}
}
...

Am 10.09.2010 19:51, schrieb Derek Chen-Becker:
> There's no direct support for this in Mapper, but I do think that it's
> something that would be nice to add, perhaps through a
> handleParseFailure def on MappedField that could be overridden with
> your own code. Right now you can achieve this by overriding setFromAny
> within a trait like:
>
> trait MappedDateParseErrorHandler[T] {
> self : MappedDate[T] =>
>
> def proxyParse(s : String) : Date = {
> LiftRules.dateTimeConverter().parseDate(s) match {
> case f @ Failure(...) => handleDateParseError(f)
> case e @ Empty => handleDateParseError(e ?~ "Unknown parse failure")
> case Full(date) => this.set(date)
> }
> // Return whatever the current value is

> this.is <http://this.is>


> }
>
> def handleDateParseError(error : Failure) : Unit // Implement this
> in your field
>
> override def setFromAny(f : Any) : Date = f match {
> case s : String => proxyParse(s)
> case (s : String) :: _ => proxyParse(s)
> case other => super.setFromAny(f)
> }
> }
>
> And then you should be able to mix it in like:
>
> object birthday extends MappedDate[Person] with
> mappedDateParseErrorHandler[Person] {
> def handleDateParseError(error : Failure) { ... }
> }
>
> This code is off the top of my head, so there may be some errors in
> it, but that's the general idea for now. Please open a ticket for
> enhanced functionality on Mapper fields to make this standard and I'll
> work on it.
>
> Derek
>
>
> On Wed, Sep 8, 2010 at 5:57 PM, Michael Strecke
> <michael...@googlemail.com

> <mailto:michael...@googlemail.com>> wrote:
>
> When a form is submitted and for example a date field contains
> letters,
> the conversion in the respective field seems to fail silently, and the
> original value is not changed.
>
> I wonder, if there is a (standard) way to inform the user of that
> event.
>
> If I understand correctly, the form validation functions are only
> called
> when a value has been successfully converted.
>
>
> Mike
>
> --
> You received this message because you are subscribed to the Google
> Groups "Lift" group.
> To post to this group, send email to lif...@googlegroups.com

> <mailto:lif...@googlegroups.com>.


> To unsubscribe from this group, send email to
> liftweb+u...@googlegroups.com

> <mailto:liftweb%2Bunsu...@googlegroups.com>.

Derek Chen-Becker

unread,
Sep 12, 2010, 9:33:44 AM9/12/10
to lif...@googlegroups.com
To open a ticket you need to be a watcher on the Lift Assembla space. As for the other changes, yeah, that looks better :) Like I said, that was off the top of my head, so my apologies that it took a lot of effort to get it working :(

Derek

Naftoli Gugenheim

unread,
Sep 21, 2010, 9:20:14 PM9/21/10
to liftweb
Perhaps instead of just an abstract method that needs to be implemented, it could act like other errors, by remembering the unparsed string.
Like this old code of mine:

trait MappedDatePlus[T<:net.liftweb.mapper.Mapper[T]] extends net.liftweb.mapper.MappedField[java.util.Date, T] {
  import net.liftweb.util.FieldError
  import net.liftweb.http.S.?
  def formatter: java.text.DateFormat = net.liftweb.util.Helpers.dateFormatter
  def format0(date: java.util.Date) = date match {
    case null => ""
    case _ => formatter.format(date)
  }
  private var inputStr: Option[String] = None

  def valNotNull = (d: java.util.Date) => d match {
    case null => FieldError(this, xml.Text(?("Date/time is not optional"))) :: Nil
    case _ => Nil
  }
  def valParsed: (java.util.Date)=>List[FieldError] = _ => {
    if(inputStr eq None) {
      Nil
    } else {
      FieldError(
        this,
        xml.Text(
          ?("Could not parse date/time") +
            (formatter match {
              case f: java.text.SimpleDateFormat => " - format: " + f.toPattern
              case _ => ""
            })
        )) :: Nil
    }
  }

  abstract override def toForm = Full(net.liftweb.http.SHtml.text(
    inputStr match {
      case Some(s) => s
      case None => format0(is)
    },
    s=>{
      try {
        set(formatter.parse(s))
      } catch {
        case e: Exception =>
          inputStr = Some(s)
      }
    }
  ))
  
  abstract override def set(d: java.util.Date) = {
    val ret = super.set(d)
    inputStr = None
    ret

Eirik Rosvold Larsen

unread,
Sep 22, 2010, 5:42:51 PM9/22/10
to lif...@googlegroups.com
+1 for a standardized feature in Lift for handling conversion failures for all Mapper/Record-classes, I can easily see this becoming tedious boilerplate code in many apps. Also, from a users perspective, there's really no difference between a conversion and validation failure.

-Eirik

David Pollak

unread,
Sep 22, 2010, 5:52:18 PM9/22/10
to lif...@googlegroups.com
On Wed, Sep 22, 2010 at 2:42 PM, Eirik Rosvold Larsen <eiri...@gmail.com> wrote:
+1 for a standardized feature in Lift for handling conversion failures for all Mapper/Record-classes, I can easily see this becoming tedious boilerplate code in many apps. Also, from a users perspective, there's really no difference between a conversion and validation failure.

Please open a ticket at http://ticket.liftweb.net
 



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Blog: http://goodstuff.im
Surf the harmonics

Ross Mellgren

unread,
Sep 22, 2010, 5:56:57 PM9/22/10
to lif...@googlegroups.com
On Sep 22, 2010, at 5:52 PM, David Pollak wrote:
On Wed, Sep 22, 2010 at 2:42 PM, Eirik Rosvold Larsen <eiri...@gmail.com> wrote:
+1 for a standardized feature in Lift for handling conversion failures for all Mapper/Record-classes, I can easily see this becoming tedious boilerplate code in many apps. Also, from a users perspective, there's really no difference between a conversion and validation failure.

Please open a ticket at http://ticket.liftweb.net

Fancy new DNS name. Gotta remember that one.

-Ross

Timothy Perrett

unread,
Sep 22, 2010, 6:09:57 PM9/22/10
to lif...@googlegroups.com
Yeah thats nice - it beats have to go to assembla every time just to paste the URL!

Eirik Rosvold Larsen

unread,
Sep 22, 2010, 7:04:29 PM9/22/10
to lif...@googlegroups.com

Derek Chen-Becker

unread,
Sep 23, 2010, 1:04:27 PM9/23/10
to lif...@googlegroups.com
Sorry, this was already opened here:

https://www.assembla.com/spaces/liftweb/tickets/643-mapper--enhanced-functionality--inform-user-about-conversion-failure

Marking the new one as a duplicate.

Derek

DChenBecker

unread,
Nov 11, 2010, 6:42:56 PM11/11/10
to Lift
I'm looking into this a bit today and I'd like to have a discussion
about how far we want to go with this. For example, the current code
in MappedLong uses StringHelpers.parseNumber (indirectly) to parse a
long. This means that a new value will always be set on the field, no
matter what the input is. Also, StringHelpers.parseNumber parses some
things that normally aren't parsed by java.lang.Long.parseLong:

scala> StringHelpers.parseNumber("12")
res0: Long = 12

scala> StringHelpers.parseNumber("abc")
res1: Long = 0

scala> StringHelpers.parseNumber(null)
res2: Long = 0

scala> StringHelpers.parseNumber("12abc")
res3: Long = 12


I feel like it would be better if an unparseable value doesn't modify
the current value of the field at all, but that's going to be a
breaking change if we do that. Note that this behavior isn't
consistent throughout Mapper: MappedDate, for instance, doesn't set a
new value unless it parses correctly. For the purposes of this
particular discussion I can make the changes strictly to MappedDate/
MappedTime/MappedDateTime, but I think that given the opportunity it
might be nice to clean things up across the board (as well as in
Record). Thoughts?

Derek

On Sep 23, 10:04 am, Derek Chen-Becker <dchenbec...@gmail.com> wrote:
> Sorry, this was already opened here:
>
> https://www.assembla.com/spaces/liftweb/tickets/643-mapper--enhanced-...
>
> Marking the new one as a duplicate.
>
> Derek
>
> On Wed, Sep 22, 2010 at 5:04 PM, Eirik Rosvold Larsen <eirir...@gmail.com>wrote:
>
>
>
> >https://liftweb.assembla.com/spaces/liftweb/tickets/655-callbacks-on-...
>
> > On Wed, Sep 22, 2010 at 11:52 PM, David Pollak <
> > feeder.of.the.be...@gmail.com> wrote:
>
> >> On Wed, Sep 22, 2010 at 2:42 PM, Eirik Rosvold Larsen <eirir...@gmail.com
> >> > wrote:
>
> >>> +1 for a standardized feature in Lift for handling conversion failures
> >>> for all Mapper/Record-classes, I can easily see this becoming tedious
> >>> boilerplate code in many apps. Also, from a users perspective, there's
> >>> really no difference between a conversion and validation failure.
>
> >> Please open a ticket athttp://ticket.liftweb.net
>
> >>> -Eirik
>
> >>> On Wed, Sep 22, 2010 at 3:20 AM, Naftoli Gugenheim <naftoli...@gmail.com
> >>>>>> > <michael.stre...@googlemail.com
> >>>>>> > <mailto:michael.stre...@googlemail.com>> wrote:
>
> >>>>>> >     When a form is submitted and for example a date field contains
> >>>>>> >     letters,
> >>>>>> >     the conversion in the respective field seems to fail silently,
> >>>>>> and the
> >>>>>> >     original value is not changed.
>
> >>>>>> >     I wonder, if there is a (standard) way to inform the user of
> >>>>>> that
> >>>>>> >     event.
>
> >>>>>> >     If I understand correctly, the form validation functions are
> >>>>>> only
> >>>>>> >     called
> >>>>>> >     when a value has been successfully converted.
>
> >>>>>> >     Mike
>
> >>>>>> >     --
> >>>>>> >     You received this message because you are subscribed to the
> >>>>>> Google
> >>>>>> >     Groups "Lift" group.
> >>>>>> >     To post to this group, send email to lif...@googlegroups.com
> >>>>>> >     <mailto:lif...@googlegroups.com>.
> >>>>>> >     To unsubscribe from this group, send email to
> >>>>>> >     liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> >>>>>> >     <mailto:liftweb%2Bunsu...@googlegroups.com<liftweb%252Buns...@googlegroups.com>
> >>>>>> >.
> >>>>>> >     For more options, visit this group at
> >>>>>> >    http://groups.google.com/group/liftweb?hl=en.
>
> >>>>>> > --
> >>>>>> > You received this message because you are subscribed to the Google
> >>>>>> > Groups "Lift" group.
> >>>>>> > To post to this group, send email to lif...@googlegroups.com.
> >>>>>> > To unsubscribe from this group, send email to
> >>>>>> > liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> >>>>>> .
> >>>>>> > For more options, visit this group at
> >>>>>> >http://groups.google.com/group/liftweb?hl=en.
>
> >>>>>> --
> >>>>>> You received this message because you are subscribed to the Google
> >>>>>> Groups "Lift" group.
> >>>>>> To post to this group, send email to lif...@googlegroups.com.
> >>>>>> To unsubscribe from this group, send email to
> >>>>>> liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> >>>>>> .
> >>>>>> For more options, visit this group at
> >>>>>>http://groups.google.com/group/liftweb?hl=en.
>
> >>>>>  --
> >>>>> You received this message because you are subscribed to the Google
> >>>>> Groups "Lift" group.
> >>>>> To post to this group, send email to lif...@googlegroups.com.
> >>>>> To unsubscribe from this group, send email to
> >>>>> liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> >>>>> .
> >>>>> For more options, visit this group at
> >>>>>http://groups.google.com/group/liftweb?hl=en.
>
> >>>>  --
> >>>> You received this message because you are subscribed to the Google
> >>>> Groups "Lift" group.
> >>>> To post to this group, send email to lif...@googlegroups.com.
> >>>> To unsubscribe from this group, send email to
> >>>> liftweb+u...@googlegroups.com<liftweb%2Bunsu...@googlegroups.com>
> >>>> .
> >>>> For more options, visit this group at
> >>>>http://groups.google.com/group/liftweb?hl=en.
>
> ...
>
> read more »

Naftoli Gugenheim

unread,
Nov 11, 2010, 7:46:40 PM11/11/10
to liftweb
What could be a justification for mutating the field on invalid input? The common use case of setting a field from a string is web forms. What should happen by default if you type "abc" into a personal information form as your age? The database should record you as being 0 years old? Or a validation error containing the invalid text you entered?


To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.

Derek Chen-Becker

unread,
Nov 11, 2010, 9:01:14 PM11/11/10
to lif...@googlegroups.com
I can't think of anything, that's just how it's currently set up. I've been thinking this afternoon and I believe that I could make this pluggable so that we maintain the current behaviors as the default, but allow for configurable parse error handling for all non-string field types.

Derek

Naftoli Gugenheim

unread,
Nov 11, 2010, 9:30:34 PM11/11/10
to liftweb
Just my opinion, but personally I'd like to get the stricter (overstatement) behavior as the default...

Jeppe Nejsum Madsen

unread,
Nov 13, 2010, 9:40:48 AM11/13/10
to lif...@googlegroups.com
DChenBecker <dchen...@gmail.com> writes:


[...]

> I feel like it would be better if an unparseable value doesn't modify
> the current value of the field at all, but that's going to be a
> breaking change if we do that. Note that this behavior isn't
> consistent throughout Mapper: MappedDate, for instance, doesn't set a
> new value unless it parses correctly. For the purposes of this
> particular discussion I can make the changes strictly to MappedDate/
> MappedTime/MappedDateTime, but I think that given the opportunity it
> might be nice to clean things up across the board (as well as in
> Record). Thoughts?

Agreed. While a breaking change, I'm not sure the impact is huge.

/Jeppe

Naftoli Gugenheim

unread,
Nov 13, 2010, 10:27:20 PM11/13/10
to liftweb
No, please don't change the behavior in Mapped(Date)(Time)! If you are editing someone's birth date and you accidentally format it improperly do you want him to be recorded born on the epoch?

Where is setFromAny used besides form submission?


$ git grep -n -C4 -e setFromAny --and \( --not -e 'def setFromAny' \) > tmp.txt

...resulted in...

framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-140-    override def setFromAny(in: Any): String = {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-141-    in match {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-142-      case JsonAST.JNull => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-143-      case JsonAST.JString(str) => this.set(str)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala:144:      case seq: Seq[_] if !seq.isEmpty => seq.map(setFromAny).apply(0)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-145-      case (s: String) :: _ => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala:146:      case s :: _ => this.setFromAny(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-147-      case null => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-148-      case s: String => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-149-      case Some(s: String) => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-150-      case Full(s: String) => this.set(s)
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-233-    override def setFromAny(in: Any): String = {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-234-    in match {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-235-      case JsonAST.JNull => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-236-      case JsonAST.JString(str) => this.set(str)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala:237:      case seq: Seq[_] if !seq.isEmpty => seq.map(setFromAny).apply(0)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-238-      case (s: String) :: _ => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala:239:      case s :: _ => this.setFromAny(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-240-      case null => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-241-      case s: String => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-242-      case Some(s: String) => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBinary.scala-243-      case Full(s: String) => this.set(s)
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-69-      case Some(b: Boolean) => this.set(b)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-70-      case Full(b: Boolean) => this.set(b)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-71-      case Empty | Failure(_, _, _) | None => this.set(false)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-72-      case (s: String) :: _ => this.set(toBoolean(s))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala:73:      case s :: _ => this.setFromAny(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-74-      case null => this.set(false)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-75-      case s: String => this.set(toBoolean(s))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-76-      case o => this.set(toBoolean(o))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedBoolean.scala-77-    }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-43-  private val data = FatLazy(defaultValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-44-  private val orgData = FatLazy(defaultValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-45-  
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-46-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala:47:   * This defines the string parsing semantics of this field. Used in setFromAny.
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-48-   * By default uses LiftRules.dateTimeConverter's parseDate; override for field-specific behavior
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-49-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-50-  def parse(s: String): Box[Date] = LiftRules.dateTimeConverter().parseDate(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-51-  /**
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-99-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-100-   * Create an input field for the item
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-101-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-102-  override def _toForm: Box[NodeSeq] =
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala:103:  S.fmapFunc({s: List[String] => this.setFromAny(s)}){funcName =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-104-  Full(<input type='text' id={fieldId}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-105-      name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-106-      value={is match {case null => "" case s => format(s)}}/>)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDate.scala-107-  }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-36-  private val data = FatLazy(defaultValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-37-  private val orgData = FatLazy(defaultValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-38-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-39-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala:40:   * This method defines the string parsing semantics of this field. Used in setFromAny.
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-41-   * By default uses LiftRules.dateTimeConverter's parseDateTime; override for field-specific behavior
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-42-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-43-  def parse(s: String): Box[Date] = LiftRules.dateTimeConverter().parseDateTime(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-44-  /**
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-91-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-92-   * Create an input field for the item
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-93-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-94-  override def _toForm: Box[NodeSeq] =
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala:95:  S.fmapFunc({s: List[String] => this.setFromAny(s)}){funcName =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-96-  Full(<input type='text' id={fieldId}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-97-      name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-98-      value={is match {case null => "" case s => format(s)}}/>)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedDateTime.scala-99-  }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-542-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-543-   * Create an input field for the item
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-544-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-545-  override def _toForm: Box[NodeSeq] =
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala:546:  S.fmapFunc({s: List[String] => this.setFromAny(s)}){funcName =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-547-    Full(<input type='text' id={fieldId}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-548-        name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-549-        value={is match {case null => "" case s => s.toString}}/>)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedField.scala-550-  }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-64-  override def setFromAny(in: Any): Long =
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-65-  in match {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-66-    case JsonAST.JNull => this.set(0L)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-67-    case JsonAST.JInt(bigint) => this.set(bigint.longValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala:68:    case o => super.setFromAny(o)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-69-  }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-70-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-71-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-72-   * Called when Schemifier adds a foreign key.  Return a function that will be called when Schemifier
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-310-      case Full(n: Number) => this.set(Full(n.longValue))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-311-      case Empty | Failure(_, _, _) => this.set(Empty)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-312-      case None => this.set(Empty)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-313-      case (s: String) :: _ => this.set(Helpers.asLong(s))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala:314:      case s :: _ => this.setFromAny(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-315-      case null => this.set(Empty)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-316-      case s: String => this.set(Helpers.asLong(s))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-317-      case o => this.set(Helpers.asLong(o))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-318-    }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-398-      case Full(n: Number) => this.set(n.longValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-399-      case Empty | Failure(_, _, _) => this.set(0L)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-400-      case None => this.set(0L)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-401-      case (s: String) :: _ => this.set(toLong(s))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala:402:      case s :: _ => this.setFromAny(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-403-      case null => this.set(0L)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-404-      case s: String => this.set(toLong(s))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-405-      case o => this.set(toLong(o))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala-406-    }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-122-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-123-   * Create an input field for the item
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-124-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-125-  override def _toForm: Box[NodeSeq] = {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala:126:    S.fmapFunc({s: List[String] => this.setFromAny(s)}){funcName =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-127-      Full(<span><input id={fieldId} type='password' name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-128-            value={is.toString}/>&nbsp;{S.??("repeat")}&nbsp;<input
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-129-            type='password' name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala-130-            value={is.toString}/></span>)
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-94-    orgData.setFrom(data)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-95-  }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-96-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-97-  override def _toForm: Box[Elem] =
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala:98:  fmapFunc({s: List[String] => this.setFromAny(s)}){name =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-99-    Full(<input type='text' id={fieldId} maxlength={maxLen.toString}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-100-        name={name}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-101-        value={is match {case null => "" case s => s.toString}}/>)}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-102-
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-115-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-116-  override def setFromAny(in: Any): String = {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-117-    in match {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-118-      case JsonAST.JNull => this.set(null) 
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala:119:      case seq: Seq[_] if !seq.isEmpty => seq.map(setFromAny).apply(0)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-120-      case (s: String) :: _ => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala:121:      case s :: _ => this.setFromAny(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-122-      case JsonAST.JString(v) => this.set(v)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-123-      case null => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-124-      case s: String => this.set(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedString.scala-125-      case Some(s: String) => this.set(s)
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-27-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-28-   * Create an input field for the item
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-29-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-30-  override def _toForm: Box[Elem] = {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala:31:    S.fmapFunc({s: List[String] => this.setFromAny(s)}){funcName =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-32-    Full(<textarea name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-33- rows={textareaRows.toString}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-34- cols={textareaCols.toString} id={fieldId}>{
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala-35-   is match {
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-45-  private val data = FatLazy(defaultValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-46-  private val orgData = FatLazy(defaultValue)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-47-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-48-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala:49:   * This method defines the string parsing semantics of this field. Used in setFromAny.
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-50-   * By default uses LiftRules.dateTimeConverter's parseTime; override for field-specific behavior
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-51-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-52-  def parse(s: String): Box[Date] = LiftRules.dateTimeConverter().parseTime(s)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-53-  /**
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-101-  /**
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-102-   * Create an input field for the item
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-103-   */
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-104-  override def _toForm: Box[NodeSeq] =
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala:105:  S.fmapFunc({s: List[String] => this.setFromAny(s)}){funcName =>
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-106-  Full(<input type='text' id={fieldId}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-107-      name={funcName}
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-108-      value={is match {case null => "" case s => format(s)}}/>)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-109-  }
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-112-    case JsonAST.JNull => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-113-    case JsonAST.JInt(v) => this.set(new Date(v.longValue))
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-114-    case "" | null => this.set(null)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-115-    case s: String => parse(s).map(s => this.set(s)).openOr(this.is)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala:116:    case x :: _ => setFromAny(x)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-117-    case f => toDate(f).map(d => this.set(d)).openOr(this.is)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-118-  }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-119-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala-120-  def jdbcFriendly(field : String) : Object = is match {
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-658-        field <- json.obj
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-659-        meth <- _mappedFields.get(field.name)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-660-      } {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-661-        val f = ??(meth, toUpdate)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala:662:        f.setFromAny(field.value)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-663-      }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-664-    }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-665-
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-666-    toUpdate
--
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-698-        field <- json.obj
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-699-        meth <- _mappedFields.get(field.name)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-700-      } {
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-701-        val f = ??(meth, ret)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala:702:        f.setFromAny(field.value)
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-703-        if (!markFieldsAsDirty) f.resetDirty
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-704-      }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-705-    }
framework/lift-persistence/lift-mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala-706-
--
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-29-object MappedDateSpecsRunner extends ConsoleRunner(MappedDateSpecs)
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-30-
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-31-object MappedDateSpecs extends Specification {
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-32-  "MappedDate" should {
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala:33:    "handle a Number in setFromAny" in {
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-34-      val dog = Dog2.create
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-35-      val currentDate = new java.util.Date()
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala:36:      dog.createdTime.setFromAny(BigInt(currentDate.getTime))
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-37-      dog.createdTime.is mustEqual currentDate
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-38-    }
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-39-  }
framework/lift-persistence/lift-mapper/src/test/scala/net/liftweb/mapper/MappedDateSpec.scala-40-}
--
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-312-  }
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-313-
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-314-  /**
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-315-  * Populate the inst's fields with the values from a DBObject. Values are set
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala:316:  * using setFromAny passing it the DBObject returned from Mongo.
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-317-  *
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-318-  * @param inst - the record that will be populated
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-319-  * @param obj - The DBObject
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-320-  * @return Box[BaseRecord]
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-321-  */
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-322-  def setFieldsFromDBObject(inst: BaseRecord, dbo: DBObject): Unit = {
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-323-    for (k <- dbo.keySet; field <- inst.fieldByName(k.toString)) {
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala:324:      field.setFromAny(dbo.get(k.toString))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-325-    }
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-326-  }
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-327-
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/MongoMetaRecord.scala-328-}
--
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-69-  def setFromAny(in: Any): Box[DBRef] = in match {
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-70-    case ref: DBRef => Full(set(ref))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-71-    case Some(ref: DBRef) => Full(set(ref))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-72-    case Full(ref: DBRef) => Full(set(ref))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala:73:    case seq: Seq[_] if !seq.isEmpty => seq.map(setFromAny).apply(0)
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-74-    case (s: String) :: _ => setFromString(s)
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-75-    case null => Full(set(null))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-76-    case s: String => setFromString(s)
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DBRefField.scala-77-    case None | Empty | Failure(_, _, _) => Full(set(null))
--
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-73-    case other => setBox(FieldHelpers.expectedA("JObject", other))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-74-  }
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-75-
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-76-  private def elem =
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala:77:    S.fmapFunc(S.SFuncHolder(this.setFromAny(_))){funcName =>
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-78-      <input type="text"
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-79-        name={funcName}
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-80-        value={valueBox.map(v => owner.meta.formats.dateFormat.format(v)) openOr ""}
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/DateField.scala-81-        tabindex={tabIndex.toString}/>
--
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-42-  def setFromAny(in: Any): Box[JObject] = in match {
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-43-    case jv: JObject => Full(set(jv))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-44-    case Some(jv: JObject) => Full(set(jv))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-45-    case Full(jv: JObject) => Full(set(jv))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala:46:    case seq: Seq[_] if !seq.isEmpty => seq.map(setFromAny).apply(0)
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-47-    case (s: String) :: _ => setFromString(s)
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-48-    case null => Full(set(null))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-49-    case s: String => setFromString(s)
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/JObjectField.scala-50-    case None | Empty | Failure(_, _, _) => Full(set(null))
--
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-69-    else
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-70-      setBox(Failure("Invalid ObjectId string: "+in))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-71-
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-72-  private def elem =
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala:73:    S.fmapFunc(S.SFuncHolder(this.setFromAny(_))){funcName =>
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-74-      <input type="text"
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-75-        name={funcName}
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-76-        value={valueBox.map(s => s.toString) openOr ""}
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/ObjectIdField.scala-77-        tabindex={tabIndex toString}/>
--
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-63-    case other => setBox(Failure("Invalid UUID string: "+in))
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-64-  }
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-65-
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-66-  private def elem =
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala:67:    S.fmapFunc(S.SFuncHolder(this.setFromAny(_))){funcName =>
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-68-      <input type="text"
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-69-        name={funcName}
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-70-        value={valueBox.map(v => v.toString) openOr ""}
framework/lift-persistence/lift-mongodb-record/src/main/scala/net/liftweb/mongodb/record/field/UUIDField.scala-71-        tabindex={tabIndex toString}/>
--
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-292-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-293-      nfl._id.setFromJValue(JString(nflid.toString))
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-294-      nfl._id.value mustEqual nflid
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-295-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala:296:      nfl._id.setFromAny(nflid)
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-297-      nfl._id.value mustEqual nflid
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-298-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala:299:      nfl._id.setFromAny(nflid.toString)
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-300-      nfl._id.value mustEqual nflid
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-301-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-302-    }
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-303-
--
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-355-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-356-      nfl._id.setFromJValue(JObject(List(JField("$oid", JString(nflid.toString)))))
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-357-      nfl._id.value mustEqual nflid
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-358-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala:359:      nfl._id.setFromAny(nflid)
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-360-      nfl._id.value mustEqual nflid
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-361-
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala:362:      nfl._id.setFromAny(nflid.toString)
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-363-      nfl._id.value mustEqual nflid
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-364-    }
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-365-  }
framework/lift-persistence/lift-mongodb-record/src/test/scala/net/liftweb/mongodb/record/CustomSerializersSpecs.scala-366-}
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-253-   *   - null|None|Empty     => setBox(defaultValueBox)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-254-   *   - f: Failure          => setBox(f)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-255-   * And usually convert the input to a string and uses setFromString as a last resort.
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-256-   * 
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala:257:   * Note that setFromAny should _always_ call setBox, even if the conversion fails. This is so that validation
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-258-   * properly notes the error.
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-259-   *
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-260-   * The method genericSetFromAny implements this guideline.
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-261-   */
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-262-  def setFromAny(in: Any): Box[MyType]
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-263-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala:264:  /** Generic implementation of setFromAny that implements exactly what the doc for setFromAny specifies, using a Manifest to check types */
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-265-  protected final def genericSetFromAny(in: Any)(implicit m: Manifest[MyType]): Box[MyType] = in match {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-266-    case value       if m.erasure.isInstance(value) => setBox(Full(value.asInstanceOf[MyType]))
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-267-    case Some(value) if m.erasure.isInstance(value) => setBox(Full(value.asInstanceOf[MyType]))
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/Field.scala-268-    case Full(value) if m.erasure.isInstance(value) => setBox(Full(value.asInstanceOf[MyType]))
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-169-      val recField = fh.field(rec)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-170-      if (fh.name == field.name)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-171-        recField.asInstanceOf[Field[FieldType, BaseRecord]].setBox(newValue)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-172-      else
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala:173:        recField.setFromAny(fh.field(original).valueBox)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-174-    }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-175-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-176-    rec
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-177-  }
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-235-  def setFieldsFromJSON(inst: BaseRecord, json: String): Box[Unit] =
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-236-    JSONParser.parse(json) match {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-237-      case Full(nvp : Map[_, _]) =>
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-238-        for ((k, v) <- nvp;
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala:239:             field <- inst.fieldByName(k.toString)) yield field.setFromAny(v)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-240-        Full(inst)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-241-      case Full(_) => Empty
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-242-      case failure => failure.asA[Unit]
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-243-    }
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-367-   * @param req - The Req to read from
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-368-   */
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-369-  def setFieldsFromReq(inst: BaseRecord, req: Req) {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-370-    for(fh <- fieldList){
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala:371:      fh.field(inst).setFromAny(req.param(fh.name))
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-372-    }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-373-  }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-374-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/MetaRecord.scala-375-  /**
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-43-    case other            => setBox(tryo(dateToCal(parseInternetDate(s))))
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-44-  }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-45-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-46-  private def elem =
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala:47:    S.fmapFunc(SFuncHolder(this.setFromAny(_))){funcName =>
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-48-      <input type="text"
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-49-        name={funcName}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-50-        value={valueBox.map(s => toInternetDate(s.getTime)) openOr ""}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/DateTimeField.scala-51-        tabindex={tabIndex toString}/>
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-39-      case (n: Number)::_  => setBox(Full(f(n)))
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-40-      case _ => genericSetFromAny(in)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-41-    }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-42-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala:43:  private def elem = S.fmapFunc((s: List[String]) => setFromAny(s)) {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-44-    funcName => <input type="text" name={funcName} value={valueBox.map(_.toString) openOr ""} tabindex={tabIndex toString}/>
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-45-  }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-46-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/NumericField.scala-47-  /**
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-64-  override def validate: List[FieldError] = runValidation(validatedValue)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-65-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-66-  override def notOptionalErrorMessage = S.??("password.must.be.set")
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-67-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala:68:  private def elem = S.fmapFunc(SFuncHolder(this.setFromAny(_))){
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-69-    funcName => <input type="password"
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-70-      name={funcName}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-71-      value={valueBox openOr ""}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/PasswordField.scala-72-      tabindex={tabIndex toString}/>}
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-34-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-35-  def maxLen = maxLength
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-36-  
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-37-  def setFromAny(in: Any): Box[String] = in match {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala:38:    case seq: Seq[_] if !seq.isEmpty => setFromAny(seq.first)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-39-    case _ => genericSetFromAny(in)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-40-  }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-41-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-42-  def setFromString(s: String): Box[String] = s match {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-43-    case "" if optional_? => setBox(Empty)
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-44-    case _                => setBox(Full(s))
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-45-  }
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-46-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala:47:  private def elem = S.fmapFunc(SFuncHolder(this.setFromAny(_))) {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-48-    funcName =>
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-49-    <input type="text" maxlength={maxLength.toString}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-50-      name={funcName}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/StringField.scala-51-      value={valueBox openOr ""}
--
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-25-import S._
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-26-import Helpers._
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-27-
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-28-trait TextareaTypedField extends StringTypedField {
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala:29:  private def elem = S.fmapFunc(SFuncHolder(this.setFromAny(_))){
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-30-    funcName => <textarea name={funcName}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-31-      rows={textareaRows.toString}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-32-      cols={textareaCols.toString}
framework/lift-persistence/lift-record/src/main/scala/net/liftweb/record/field/TextareaField.scala-33-      tabindex={tabIndex toString}>{valueBox openOr ""}</textarea>
--
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-96-
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-97-      private def fieldFor(o: AnyRef) = getter.get.invoke(o).asInstanceOf[TypedField[AnyRef]]
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-98-
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-99-      override def setFromResultSet(target: AnyRef, rs: ResultSet, index: Int) =
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala:100:        fieldFor(target).setFromAny(Box!!resultSetHandler(rs, index))
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-101-
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-102-      override def get(o: AnyRef) = fieldFor(o).valueBox match {
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-103-        case Full(c: Calendar) => new Timestamp(c.getTime.getTime)
framework/lift-persistence/lift-squeryl-record/src/main/scala/net/liftweb/squerylrecord/RecordMetaDataFactory.scala-104-        case Full(other) => other
--
framework/src/changes/changes.xml-542-      <action dev="hoffrocket" type="fix" issue="411" system="assembla">
framework/src/changes/changes.xml-543-        MappedLongForeignKey apply() methods which take reference now prime the Obj
framework/src/changes/changes.xml-544-      </action>
framework/src/changes/changes.xml-545-      <action dev="hoffrocket" type="fix" issue="427" system="assembla">
framework/src/changes/changes.xml:546:        MappedDate and MappedDateTime setFromAny now handle Numbers (millis)
framework/src/changes/changes.xml-547-      </action>
framework/src/changes/changes.xml-548-      <action dev="hoffrocket" type="fix" issue="426" system="assembla">
framework/src/changes/changes.xml-549-        MappedString.crop gracefully handles null
framework/src/changes/changes.xml-550-      </action>


Naftoli@NAFTOLI-PC /c/dev/liftweb (master)
$ git grep -n -C4 -e jdbcFriendly --and \( --not -e 'def jdbcFriendly(' \) > tmp.txt

Naftoli@NAFTOLI-PC /c/dev/liftweb (master)
$


Am I missing something?

Derek Chen-Becker

unread,
Nov 14, 2010, 11:51:48 AM11/14/10
to lif...@googlegroups.com
I think you misunderstood. Currently, MappedDate/MappedDateTime do not update the field unless the input parses. *That behavior* is what I think all of the field types should exhibit, but currently setting someone's age (object age extends MappedLong(this)) to "foo" results in them being zero years old.

To reiterate, I think that the other fields should be modified to behave like Mapped(Date|Time|DateTime), not the other way around.

Derek

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.

David Brooks

unread,
Nov 16, 2010, 1:41:48 PM11/16/10
to lif...@googlegroups.com
Hi Derek, Naftoli,

I have to say I'm quite surprised by the "setFromAny" behaviour in Lift - it seems nice and neat until you run up against it. Thoughts inlined below...

> On Sat, Nov 13, 2010 at 8:27 PM, Naftoli Gugenheim <nafto...@gmail.com>wrote:
>
>> No, please don't change the behavior in Mapped(Date)(Time)! If you are
>> editing someone's birth date and you accidentally format it improperly do you want him to be recorded born on the epoch?
>>
>> Where is setFromAny used besides form submission?

I just relaxed a constraint on a MappedInt to allow it to include 0 as a valid value (previously it was 1-5, now it's 0-5). In doing this, the behaviour of my form fields changed, so that now entering "abc" appears to be a valid value because it autoconverts to 0. I consider this analogous to Naftoli's scenario above.

Leaving the existing birth date unchanged or making it the epoch (or setting "abc" to 0 in a MappedInt) seems irrelevant - in either case you want to make it clear to the user that (a) they entered some bad data; and (b) you haven't allowed them them bugger up their saved data. FieldErrors is the usual way to do that, and in my case I had to jump through hoops to workaround the parse failure.

On 14 Nov 2010, at 16:51, Derek Chen-Becker wrote:

> I think you misunderstood. Currently, MappedDate/MappedDateTime do not
> update the field unless the input parses. *That behavior* is what I think
> all of the field types should exhibit, but currently setting someone's age
> (object age extends MappedLong(this)) to "foo" results in them being zero
> years old.
>
> To reiterate, I think that the other fields should be modified to behave
> like Mapped(Date|Time|DateTime), not the other way around.

I agree with Derek that there shouldn't be a special case for dates.

With that in mind, can I make the following suggestion for a non-breaking change:

[1] add a method "setFromAnyDefaultsTo"* to MappedField[O,T] that returns a T. This would be trivially overridden to return the current value, defaultValue, or any other sensible default (e.g. 0 for MappedInt, or -1 in my case). Alternatively, the developer can choose to simply throw an exception here.

(*rename as you see fit - I've acquired a nasty habit of verbose method and variable naming :$)

[2] provide variants of toXXX(Any) that allow a default value to be specified, e.g:

def toInt(default: => Int)(in: Any) ...

[2] alter all the setFromAny methods to use these default values:

For MappedInt, this would change from:

override def setFromAny(in: Any): Int = {
in match {
case n: Int => this.set(n)
case JsonAST.JInt(bigint) => this.set(bigint.intValue)
case n: Number => this.set(n.intValue)
case (n: Number) :: _ => this.set(n.intValue)
case Some(n: Number) => this.set(n.intValue)
case Full(n: Number) => this.set(n.intValue)
case None | Empty | Failure(_, _, _) => this.set(0)
case (s: String) :: _ => this.set(toInt(s))
case null => this.set(0)
case s: String => this.set(toInt(s))
case o => this.set(toInt(o))
}
}

to:

override def setFromAnyDefaultsTo = 0

override def setFromAny(in: Any): Int = {
in match {
case n: Int => this.set(n)
case JsonAST.JInt(bigint) => this.set(bigint.intValue)
case n: Number => this.set(n.intValue)
case (n: Number) :: _ => this.set(n.intValue)
case Some(n: Number) => this.set(n.intValue)
case Full(n: Number) => this.set(n.intValue)
case None | Empty | Failure(_, _, _) => this.set(setFromAnyDefaultsTo)
case (s: String) :: _ => this.set(asInt(s).openOr(setFromAnyDefaultsTo))
case null => this.set(setFromAnyDefaultsTo)
case s: String => this.set(asInt(s).openOr(setFromAnyDefaultsTo))
case o => this.set(toInt(setFromAnyDefaultsTo)(o)))
}
}

MappedDate could be updated along similar lines, with:

setFromAnyDefaultsTo = this.is

This should be a non-breaking change, but would also allow coders to handle the problem cases however they see fit. Admittedly, it would also be quite a big change...

Cheers,
D

ps. On a related note, I think it would be really nice to be able to set MappedDate(Time) using Full(d: Date) or Empty. I raised a ticket on this a while back:

https://www.assembla.com/spaces/liftweb/tickets/681-make-mappeddatetime-behave-consistently-with-box%5Bdate%5D

but didn't know to whom I should assign it...

Naftoli Gugenheim

unread,
Nov 16, 2010, 6:11:57 PM11/16/10
to liftweb
Interesting approach. Personally I would modify your suggestion so that it defaults to remaining with the current value, but having an easy hook to go back to the old value is okay.
I think it's a conflict between the possibility of a breaking change (although I find it hard to believe that many people rely on the old behavior; use case anyone?), and the principle of least surprise. The default should not be destructive. If the programmer hasn't explicitly given permission to erase the field's value and it's not obvious that's what he wants, than don't do it. To me it's the same reason why "delete_!" has an exclamation point.

David, are you saying that you prefer setting it to 0 yourself? I think Derek agrees with me.

Is there anyone reading this who knows of a use case for the old behavior -- that calling setFromAny on a field, with an invalid value, should reset the field to its default value (such as zero)?


David Brooks

unread,
Nov 16, 2010, 8:14:05 PM11/16/10
to lif...@googlegroups.com
Hi Naftoli,

On 16 Nov 2010, at 23:11, Naftoli Gugenheim wrote:

> Interesting approach. Personally I would modify your suggestion so
> that it defaults to remaining with the current value, but having an
> easy hook to go back to the old value is okay.

Completely agree. More below.

> I think it's a conflict between the possibility of a breaking change
> (although I find it hard to believe that many people rely on the old
> behavior; use case anyone?), and the principle of least surprise.
> The default should not be destructive. If the programmer hasn't
> explicitly given permission to erase the field's value and it's not
> obvious that's what he wants, than don't do it. To me it's the same
> reason why "delete_!" has an exclamation point.

True, but who is being surprised here? If the user enters "abc" into a
field, but then reloads the page and sees "21/12/2012" in its place
they will probably be quite surprised. The programmer will likely not
know much about this (as a silent failure), so won't be at all
surprised ;)

Incidentally, I was quite surprised that the default conversions
existed at all - I thought I was going to have to do all that legwork
myself!

> David, are you saying that you prefer setting it to 0 yourself? I
> think Derek agrees with me.

Not quite. I certainly agree with you both that using a non-
destructive default for conversion-failure is preferable to a
destructive one. However, the silent failure of, say, a user entering
"abc" into a date field, is still problematic.

My preferred solution would be to make all MappedField subtypes Boxed,
and have conversion failure result in a Failure value for the
MappedField. The usual FieldError mechanisms could detect this and
inform the user accordingly. However, that is a gigantic change that I
would expect to get laughed off the table.

I can completely understand why exceptions were avoided, which leaves
us with default values. My suggestion was to introduce some
flexibility, with the method:

def setFromAnyDefaultsTo: T

While this would certainly be a large change, it would be backwards-
compatible. It could trivially be turned into a breaking change, too,
if the consensus is for non-destructive conversion-failure default
(and I'd support this):

def setFromAnyDefaultsTo = this.is

The real benefit is that the programmer can override a single, simple
method to reserve a default value for conversion failure - be that
value the epoch, 0, -1, Int.MinValue or Double.NaN. They can use
validation to protect against thus reserved value, and easily generate
FieldErrors to avoid the silent failure problem. Heck, they can even
throw an exception if they fancy dealing with the fallout.

> Is there anyone reading this who knows of a use case for the old
> behavior -- that calling setFromAny on a field, with an invalid
> value, should reset the field to its default value (such as zero)?


Not me.

Cheers,
D

Derek Chen-Becker

unread,
Nov 16, 2010, 9:46:59 PM11/16/10
to lif...@googlegroups.com
Actually, I was thinking of hooking in a per-field parse error handler method that would default to a globally-defined handler. Then you could either override the global handler or do per-field error handling on invalid conversions.

Derek

On Tue, Nov 16, 2010 at 6:14 PM, David Brooks <davidjam...@gmail.com> wrote:
Hi Naftoli,


On 16 Nov 2010, at 23:11, Naftoli Gugenheim wrote:

Interesting approach. Personally I would modify your suggestion so that it defaults to remaining with the current value, but having an easy hook to go back to the old value is okay.

Completely agree.  More below.


I think it's a conflict between the possibility of a breaking change (although I find it hard to believe that many people rely on the old behavior; use case anyone?), and the principle of least surprise. The default should not be destructive. If the programmer hasn't explicitly given permission to erase the field's value and it's not obvious that's what he wants, than don't do it. To me it's the same reason why "delete_!" has an exclamation point.

True, but who is being surprised here? If the user enters "abc" into a field, but then reloads the page and sees "21/12/2012" in its place they will probably be quite surprised. The programmer will likely not know much about this (as a silent failure), so won't be at all surprised ;)

Incidentally, I was quite surprised that the default conversions existed at all - I thought I was going to have to do all that legwork myself!


David, are you saying that you prefer setting it to 0 yourself? I think Derek agrees with me.

Not quite.  I certainly agree with you both that using a non-destructive default for conversion-failure is preferable to a destructive one.  However, the silent failure of, say, a user entering "abc" into a date field, is still problematic.


My preferred solution would be to make all MappedField subtypes Boxed, and have conversion failure result in a Failure value for the MappedField. The usual FieldError mechanisms could detect this and inform the user accordingly. However, that is a gigantic change that I would expect to get laughed off the table.

I can completely understand why exceptions were avoided, which leaves us with default values.  My suggestion was to introduce some flexibility, with the method:

def setFromAnyDefaultsTo: T

While this would certainly be a large change, it would be backwards-compatible. It could trivially be turned into a breaking change, too, if the consensus is for non-destructive conversion-failure default (and I'd support this):


def setFromAnyDefaultsTo = this.is

The real benefit is that the programmer can override a single, simple method to reserve a default value for conversion failure - be that value the epoch, 0, -1, Int.MinValue or Double.NaN.  They can use validation to protect against thus reserved value, and easily generate FieldErrors to avoid the silent failure problem.  Heck, they can even throw an exception if they fancy dealing with the fallout.


Is there anyone reading this who knows of a use case for the old behavior -- that calling setFromAny on a field, with an invalid value, should reset the field to its default value (such as zero)?


Not me.

Cheers,
D

--

Naftoli Gugenheim

unread,
Nov 16, 2010, 9:51:23 PM11/16/10
to liftweb
On Tue, Nov 16, 2010 at 8:14 PM, David Brooks <davidjam...@gmail.com> wrote:
Hi Naftoli,


On 16 Nov 2010, at 23:11, Naftoli Gugenheim wrote:

Interesting approach. Personally I would modify your suggestion so that it defaults to remaining with the current value, but having an easy hook to go back to the old value is okay.

Completely agree.  More below.

Ah, okay. So so far no one has disagreed. :)
 


I think it's a conflict between the possibility of a breaking change (although I find it hard to believe that many people rely on the old behavior; use case anyone?), and the principle of least surprise. The default should not be destructive. If the programmer hasn't explicitly given permission to erase the field's value and it's not obvious that's what he wants, than don't do it. To me it's the same reason why "delete_!" has an exclamation point.

True, but who is being surprised here? If the user enters "abc" into a field, but then reloads the page and sees "21/12/2012" in its place they will probably be quite surprised. The programmer will likely not know much about this (as a silent failure), so won't be at all surprised ;)

21/12/2012 being the previous value or the zero value? I was referring to a scenario where it gets reset to zero or equivalent.
And if the programmer tests the app then he will be surprised. :)
 

Incidentally, I was quite surprised that the default conversions existed at all - I thought I was going to have to do all that legwork myself!


David, are you saying that you prefer setting it to 0 yourself? I think Derek agrees with me.

Not quite.  I certainly agree with you both that using a non-destructive default for conversion-failure is preferable to a destructive one.  However, the silent failure of, say, a user entering "abc" into a date field, is still problematic.


My preferred solution would be to make all MappedField subtypes Boxed, and have conversion failure result in a Failure value for the MappedField. The usual FieldError mechanisms could detect this and inform the user accordingly. However, that is a gigantic change that I would expect to get laughed off the table.

See also my proposed solution earlier in this thread. I agree 100% that this is necessary and I think it should be enabled by default.
But I don't think it makes sense to result in a Failure value for the MappedField, because then once you enter an invalid value there's no way to go back. Rather, it should store the error condition separately, so that it can either prevent you from proceeding or allow you to keep the old value.
Also, it could be useful to record not just the fact that there is an error message, but the actual text entered, as a separate String, so that when the form is redisplayed it could show the invalid entry together with an error message.
This is what my code does, although perhaps "inputStr" should be renamed "unparsedInput"...

 

I can completely understand why exceptions were avoided, which leaves us with default values.  My suggestion was to introduce some flexibility, with the method:

def setFromAnyDefaultsTo: T

While this would certainly be a large change, it would be backwards-compatible. It could trivially be turned into a breaking change, too, if the consensus is for non-destructive conversion-failure default (and I'd support this):


def setFromAnyDefaultsTo = this.is

The real benefit is that the programmer can override a single, simple method to reserve a default value for conversion failure - be that value the epoch, 0, -1, Int.MinValue or Double.NaN.  They can use validation to protect against thus reserved value, and easily generate FieldErrors to avoid the silent failure problem.  Heck, they can even throw an exception if they fancy dealing with the fallout.


Is there anyone reading this who knows of a use case for the old behavior -- that calling setFromAny on a field, with an invalid value, should reset the field to its default value (such as zero)?


Not me.

Cheers,
D

--

Naftoli Gugenheim

unread,
Nov 16, 2010, 9:52:34 PM11/16/10
to liftweb
Sounds good!
Similar to how parsing/formatting of dates works?

David Brooks

unread,
Nov 17, 2010, 5:22:25 AM11/17/10
to lif...@googlegroups.com
Hi guys,

I don't have any more to say about the original post, except to agree with Derek's plan of attack. However, I do want to clarify something for my own understanding.

On 17 Nov 2010, at 02:51, Naftoli Gugenheim wrote:

> See also my proposed solution earlier in this thread. I agree 100% that this is necessary and I think it should be enabled by default.
> But I don't think it makes sense to result in a Failure value for the
> MappedField, because then once you enter an invalid value there's no way to go back.

I thought 'was' provided that capability - is that incorrect? I assume it would work thus: bad data input would result in a Failure, so there's no way to save it in a bad state. That Failure could contain the input string in a nicely formatted error message, and you can still get the old value out of 'was' without issue.

I'm sure I'm missing something subtle here, having not used 'was' previously.

Cheers,
D

Jeppe Nejsum Madsen

unread,
Nov 17, 2010, 5:40:49 AM11/17/10
to lif...@googlegroups.com
David Brooks <davidjam...@gmail.com> writes:


[...]


> ps. On a related note, I think it would be really nice to be able to set MappedDate(Time) using Full(d: Date) or Empty. I raised a ticket on this a while back:
>
> https://www.assembla.com/spaces/liftweb/tickets/681-make-mappeddatetime-behave-consistently-with-box%5Bdate%5D
>
> but didn't know to whom I should assign it...

Someone who feel like fixing it will assign it :-) That someone might be
me. I just noticed that special case in our own implementation of
MappedDate and wondered why it was there until i looked at the original
MappedDate....

/Jeppe

David Brooks

unread,
Nov 17, 2010, 5:47:08 AM11/17/10
to lif...@googlegroups.com
On 17 Nov 2010, at 10:40, Jeppe Nejsum Madsen wrote:

> Someone who feel like fixing it will assign it :-)

Phew! I'd seen a few mails to this list saying "raise a ticket and assign it to me" and I was worried I'd done something wrong by not assigning it. Thank you!

Cheers,
D

Derek Chen-Becker

unread,
Nov 17, 2010, 11:23:21 AM11/17/10
to lif...@googlegroups.com
OK, I've put a very early implementation of a few parsers up on the dcb-issue-643 branch so that we can have some discussion:

https://github.com/lift/lift/commit/fb8f1faf22298de050cd79173f577ae205ab544a

Basically, the MappedField trait has been modified to add some hooks for custom per-field parsing and parse error handling. The real work is done via the MapperParsers trait hooked via the MapperRules.parser variable. I've provided a default implementation of MapperParsers (DefaultMapperParsers) that conforms to the current behavior (currently, I've only updated MappedInt), as well as a NewMapperParsers object that implements non-destructive parsing with configurable error handling. This is just meant to be a starting point before I overhaul the whole of Mapper, so input would be appreciated.

Derek

D

David Brooks

unread,
Nov 17, 2010, 12:51:39 PM11/17/10
to lif...@googlegroups.com
Hi Derek,

On 17 Nov 2010, at 16:23, Derek Chen-Becker wrote:

> OK, I've put a very early implementation of a few parsers up on the
> dcb-issue-643 branch so that we can have some discussion:
>
> https://github.com/lift/lift/commit/fb8f1faf22298de050cd79173f577ae205ab544a
>
> Basically, the MappedField trait has been modified to add some hooks for
> custom per-field parsing and parse error handling. The real work is done via the MapperParsers trait hooked via the MapperRules.parser variable.
>
> I've provided a default implementation of MapperParsers (DefaultMapperParsers) that conforms to the current behavior (currently, I've only updated MappedInt), as well as a NewMapperParsers object that implements non-destructive parsing with configurable error handling.

At first glance I thought the pattern was quite complex (passing the MappedFields around), but I can't see an obvious refactoring yet. I'll have a think about this later this evening...

However, I do like the fact that the default behaviour can be overridden on a per-type (MapperParsers.parseErrorHandler) or a per-field (MappedField.parseErrorHandler) basis. That's a substantial improvement on what I was suggesting.

> This is just meant to be a starting point before I overhaul the whole of Mapper, so input would be appreciated.

Just to double-check, do you intend to do something with the non-string lines in setFromAny? I.e. these ones from MappedInt:

case None | Empty | Failure(_, _, _) => this.set(0)

case null => this.set(0)
case o => this.set(toInt(o))

The ones with "this.set(0)" are the ones I was grumbling about in my earlier emails. I think it's important that the pattern covers those too (and non-string parsing values), but I presume these are just artefacts of the prototyping process.

Looks promising...

Cheers,
D

Derek Chen-Becker

unread,
Nov 17, 2010, 2:31:44 PM11/17/10
to lif...@googlegroups.com
Passing the MappedField around lets you get at the displayName and set methods of the field from the global parseErrorHandler, although there are certainly other ways to approach this. In terms of handling nulls, Boxes, etc, that's an even larger scope than what I was trying to tackle here, but it's probably good to discuss that as well. The code I checked in strictly deals with parsing Strings, which have pretty clear semantics of parseable/not parseable. Empty/None/null have special meaning for some fields (FK fields, in particular), so dealing with that is going to make it a bit more complex. Let me think about it and see if I can come up with a unified replacement for setFromAny that deals with all of these issues.

Derek


Cheers,
D

David Brooks

unread,
Nov 18, 2010, 8:20:06 AM11/18/10
to lif...@googlegroups.com
Hi Derek,

On 17 Nov 2010, at 19:31, Derek Chen-Becker wrote:

> Passing the MappedField around lets you get at the displayName and set
> methods of the field from the global parseErrorHandler, although there are certainly other ways to approach this.

Yes, make sense. I had a fiddle with the code myself and just managed to justify your proposal.

> Let me think about it and see if I can come up with a unified replacement for setFromAny that deals with all of these issues.

Your proposal will fix my problem regardless. I was just being fussy about the asymmetric treatment of String values vs. everything else.

On an unrelated note to the parsing, but still on the topic of setFromAny... those hard-coded 0's in MappedInt (and 0L in MappedLong) - If they are intended to provide resetting capabilities via Empty/None/null, shouldn't they set back to defaultValue, not 0(/0L)?

Cheers,
D

Naftoli Gugenheim

unread,
Nov 18, 2010, 6:55:26 PM11/18/10
to liftweb
I believe you are correct.



Cheers,
D

Naftoli Gugenheim

unread,
Nov 22, 2010, 12:50:33 AM11/22/10
to liftweb
Why is parsing per MetaMapper, not just per field?

Derek Chen-Becker

unread,
Nov 22, 2010, 9:58:34 AM11/22/10
to lif...@googlegroups.com
It is per field. Check out the additions to MappedField that add configurable per-field parsing and parse error handling:

  /**
   * This defines a per-field method that can be used to parse the field
   * value from a String. You can set global parsing for a given type
   * using the MapperParsers trait and the MapperRules.parsers variable.
   */
  val parseValue : Box[String => FieldType] = Empty

  /**
   * This defines a per-field parse error handler. If you want
   * to override a specific field's parse error handling, provide
   * a function here. You can set a global parse error handler
   * using the MapperParsers trait and the MapperRules.parsers variable.
   */
  val parseErrorHandler : Box[String => FieldType] = Empty

The global parser will use the per-field parser if it's defined.

Derek

David Pollak

unread,
Dec 14, 2010, 5:09:56 PM12/14/10
to lif...@googlegroups.com
Folks,

Sorry for coming late to the discussion.

What if we had 2 instance variables for each field... the "current value" field and the "what the user last entered".  The former is set to the latter if and only if validation passes.  This also allows us to have transformative filters (T => Box[T2]) that bridge between the String input and the actual type of the field.

We might even make this part of BaseField so it would migrate up to Mapper and Record fields.

Sound reasonable?

Thanks,

David

Derek Chen-Becker

unread,
Dec 16, 2010, 11:25:31 AM12/16/10
to lif...@googlegroups.com
That sounds reasonable to me. I think it would still be nice to allow for user-configurable parsing functions, particularly since a lot of the current parsing results in "0" for invalid formats and I can see that being a problem for some people (it has been for me in the past). Did you take a look at the small prototype I put together?

Derek

David Pollak

unread,
Dec 16, 2010, 11:59:53 AM12/16/10
to lif...@googlegroups.com
On Thu, Dec 16, 2010 at 8:25 AM, Derek Chen-Becker <dchen...@gmail.com> wrote:
That sounds reasonable to me. I think it would still be nice to allow for user-configurable parsing functions

Definitely!
 
, particularly since a lot of the current parsing results in "0" for invalid formats and I can see that being a problem for some people (it has been for me in the past). Did you take a look at the small prototype I put together?

Not yet.  It's on my list. ;-)

Derek Chen-Becker

unread,
Dec 16, 2010, 12:35:14 PM12/16/10
to lif...@googlegroups.com
OK, I'll wait for your feedback and then we can hash out the whole shebang ;)

David Brooks

unread,
Dec 17, 2010, 11:28:31 AM12/17/10
to lif...@googlegroups.com

On 14 Dec 2010, at 22:09, David Pollak wrote:

> Folks,
>
> What if we had 2 instance variables for each field... [...]
>
> Sound reasonable?

Yup.

Cheers,
D

Serioga

unread,
Jan 25, 2011, 11:42:01 AM1/25/11
to Lift
Hello everyone.

So what is the status of discussed issue?

Derek Chen-Becker

unread,
Jan 25, 2011, 5:37:40 PM1/25/11
to lif...@googlegroups.com
Still pending:

https://www.assembla.com/spaces/liftweb/tickets/643-mapper--enhanced-functionality--inform-user-about-conversion-failure

I have some preliminary work on branch dcb-issue-643:

https://github.com/lift/lift/tree/dcb-issue-643

I'm waiting to do more work on it because David had some ideas he was going to incorporate.

Derek

On Tue, Jan 25, 2011 at 9:42 AM, Serioga <sergey....@gmail.com> wrote:
Hello everyone.

So what is the status of discussed issue?

Jeppe Nejsum Madsen

unread,
Jan 27, 2011, 3:31:44 AM1/27/11
to lif...@googlegroups.com
Derek Chen-Becker <dchen...@gmail.com> writes:

> Still pending:
>
> https://www.assembla.com/spaces/liftweb/tickets/643-mapper--enhanced-functionality--inform-user-about-conversion-failure
>
> I have some preliminary work on branch dcb-issue-643:
>
> https://github.com/lift/lift/tree/dcb-issue-643
>
> I'm waiting to do more work on it because David had some ideas he was going
> to incorporate.

I'm still trying to find time to look at LiftScreen thoroughly, but one
of the things I think we need is to unify (to the extent possible) the
different form fields across Mapper, Record, Screen etc. This goes to
display, conversion & validation.

/Jeppe

Damian H

unread,
Oct 24, 2011, 11:20:10 AM10/24/11
to lif...@googlegroups.com
Hi, 

It looks to me like the two tickets referring to the work arising from this thread have a circular reference going on: they are both marked as duplicates of each other therefore have both been cancelled:


Am I reading the ticket information correctly? Or has the work on this been canned? Or is it on-going under a different ticket?

Thanks

Damian.

David Pollak

unread,
Oct 24, 2011, 11:50:31 AM10/24/11
to lif...@googlegroups.com
643 is still live and it's assigned to Derek.  Since his latest baby came along and then he switched jobs, Lift has been a lower priority for him.

--
Lift, the simply functional web framework: http://liftweb.net



--
Lift, the simply functional web framework http://liftweb.net

Damian H

unread,
Oct 24, 2011, 12:02:59 PM10/24/11
to lif...@googlegroups.com
ah right, I was misinterpreting 'Milestone changed from 2.3-RC1 to -none-' . I should have paid more attention to the 'In Progess / Accepted' field. Thanks for the clarification. 
Reply all
Reply to author
Forward
0 new messages