0

I'm new to both Lift and Squeryl.

I was following the example on the lift cookbook on how to create a Schema and some tables. I managed to do so and to insert records, this is my schema code:

object PortfolioSchema extends Schema {

    val systemConfigurations = table[SystemConfiguration]

    on(systemConfigurations) {
       sc =>
         declare(
           sc.name defineAs (unique)
       )
    }

    class SystemConfiguration extends Record[SystemConfiguration] with KeyedRecord[Long] {

    override def meta: MetaRecord[SystemConfiguration] = SystemConfiguration

    override val idField = new LongField(this)

    val name = new StringField(this, 256) {
      override def validations = valUnique("unique.name") _ :: super.validations

      override def setFilter = trim _ :: super.setFilter
    }

    private def valUnique(errorMsg: => String)(name: String): List[FieldError] = SystemConfiguration.unique_?(name) match {
      case false => FieldError(this.name, S ? errorMsg) :: Nil
      case true => Nil
    }

}

object SystemConfiguration extends SystemConfiguration with MetaRecord[SystemConfiguration] {

    def unique_?(name: String) = from(systemConfigurations) {
      p => where(lower(p.name) === lower(name)) select (p)
    }.isEmpty

  }

}

Long story short, I just have an entity with a field name that is unique and a validation function that checks this property and returns a FieldError that is defined form the Lift library like follows:

case class FieldError(field: FieldIdentifier, msg: NodeSeq) {
   override def toString = field.uniqueFieldId + " : " + msg
}

object FieldError {
   import scala.xml.Text
   def apply(field: FieldIdentifier, msg: String) = new FieldError(field, Text(msg))
}

Basically what it does it attaches the field.uniqueFieldId to the error message I specify, so if I use it like this:

valUnique("unique.name") _

What I get in the List[FieldError] is Full(name_id) : unique.name

This doesn't look right to me because to get my error message I'll have to split the string and remember the field identifier, is there any better way to handle this error case?

Ende Neu
  • 15,581
  • 5
  • 57
  • 68

2 Answers2

1

The fieldId : msg string is the toString representation of the FieldError class. That toString method is only meant to be used for logging / debugging though. There is no reason you should see it appear anywhere within your app. Generally you will validate your object and delegate the display of FieldErrors to Lift using something like S.error(listOfFieldErrors) and Lift's Msgs snippet. If you use some of the built in helpers for form generation like Crudify or LiftScreen the validation of fields and addition of the errors is handled for you.

Dave Whittaker
  • 3,102
  • 13
  • 14
0
object PortfolioSchema extends Schema {

object name extends StringField(this, 256) {
  override def validations = valUnique(S ? ("unique.name")) _ :: super.validations

  def valUnique(errorMsg: => String)(value: ValueType): List[FieldError] =
    if (SystemConfiguration.unique_?(value))
      Nil
    else
      FieldError(this, Text(errorMsg)) :: Nil
}

This should work. The main difference is how you reference the field value and field identifier itself.

yǝsʞǝla
  • 16,272
  • 2
  • 44
  • 65
  • I get an error when trying to compile at `p => where(lower(p.name) === lower(name)) select (p)`, `recursive value name needs type` at `p.name` – Ende Neu Mar 09 '14 at 16:07
  • I had to explicitly add the return type to the `unique_?` function, anyway nothing has changed, I keep getting the full message `Full(name_id) : unique.name`. – Ende Neu Mar 09 '14 at 16:20
  • Do you use resource bundles? https://www.assembla.com/spaces/liftweb/wiki/Internationalization/print. `S ?` will try to lookup proper message with key `unique.name`. – yǝsʞǝla Mar 09 '14 at 16:24
  • I didn't get that far for now but thanks for the pointer on resource bundles. What I don't understand here is, `S ?` will lookup the message with the specified key but this will still be processed and added to the `List[FieldError]` and as I posted in my question this will always contain a String like `field.uniqueFieldId + " : " + msg`. Am I missing something? – Ende Neu Mar 09 '14 at 16:39
  • If `S ?` does not find any message to replace original `unique.name` with, it will leave it as it is, otherwise you will get a nicely worded error, or even translated one based on the locale. – yǝsʞǝla Mar 09 '14 at 17:38
  • You don't have to use `S ?` and you can write any `String` error message that you want. `S` gives you session environment and looks up resources for you which is nice if you have multilingual site or you want to separate error definition in code from error text in configuration. – yǝsʞǝla Mar 09 '14 at 17:41
  • I thank you for your help but either you haven't read my question correctly or I haven't managed to explain myself. I'm not looking for `i18n` or string lookup, as you said in a comment I could pass a simple string in the function and obtain the same result, the problem is the result itself, the output will always be a concatenation of the field unique id and the error message because of how the `FieldError` class `apply` method is defined and as I said, I would like to obtain only the message when I validate the DB operation without having to recur to string parsing functions. – Ende Neu Mar 09 '14 at 18:05