Как обрезать строку параметров в сопоставлении столбцов Slick при использовании Play Scala

Каков правильный способ и где это правильное место, чтобы обрезать значение из столбца базы данных с фиксированными символами при использовании платформы Play с Slick?

Причина, по которой я хочу обрезать строку, заключается в том, что в схеме базы данных указан тип столбца character(40), а не тип character varying.

У меня есть этот класс корпуса:

case class Test(id: Long, trimMe: Option[String])

У меня есть это отношение таблицы Slick:

class Tests(tag: Tag) extends Table[Test](tag, "test") {

  def id     = column[Long  ]("test_id", O.PrimaryKey, O.AutoInc)
  def trimMe = column[String]("trim_me"                         )

  def * = (id, trimMe) <> (Test.tupled, Test.unapply _)

}

У меня есть этот тестовый класс с отображением JSON:

object TrimTest {

  implicit val testWrite = new Writes[Test] {
    def writes(test: Test) = Json.obj(
      "id"   -> test.id    ,
      "trim" -> test.trimMe
    )}
}

Все это работает, но возвращает строку, заполненную пробелами.

Я попробовал несколько вариантов обрезки в картографе JSON:

object TrimTest {

  implicit val testWrite = new Writes[Test] {
    def writes(test: Test) = Json.obj(
      "id"    -> test.id                              ,
      "trim1" -> test.trimMe.map(_.trim)              ,
      "trim2" -> test.trimMe.fold("") {_.trim}        ,
      "trim3" -> test.trimMe.map(_.trim).getOrElse("")
    )}
}

trim1 выше работает, но возвращает null, если необязательного значения нет.

trim2 действительно работает во всех случаях, но я видел, как в разных местах говорится, что map затем getForElse является «более идиоматической Scala», чем использование fold.

trim3 только что превзошел предел моего нынешнего понимания Scala и показывает мои намерения, но не компилируется.

Ошибка компиляции в случае trim3:

несоответствие типов; найдено: Требуемый объект: play.api.libs.json.Json.JsValueWrapper

Я, конечно, могу жить с использованием fold, но как это обычно делается?


person caprica    schedule 04.08.2014    source источник


Ответы (2)


Как насчет получения значения и последующей обрезки?

scala> val strOpt = Option("Some string not trimmed    ")
strOpt: Option[String] = Some(Some string not trimmed    )

scala> strOpt.getOrElse("").trim
res0: String = Some string not trimmed

scala> val strNone = Option(null)
strNone: Option[Null] = None

scala> strNone.getOrElse("").trim
res2: String = ""

Редактировать:

У вас есть строка Test, которая представляет собой класс case с двумя полями, id и trimMe, вы хотите сопоставить этот класс с JSON, но проблема в том, что вы также хотите trim это поле trimeMe.

Если у вас есть Column[String], с точки зрения Slick это означает необязательное поле, но ваш класс дела имеет необязательное поле, либо оба (Test, и Tests) имеют необязательное поле trimMe (это означает, что столбец) или нет (это означает, что столбец является обязательным).

В конце концов, класс case, который у вас есть, представляет собой представление строки, которая есть в вашей базе данных, и то, что возвращают запросы Slick (*), он должен отражать ваше объявление схемы.

Для проблемы trim

  • если trimMe Column[Option[String]], в вашем классе дела есть trimMe: Option[String], поэтому вы можете getOrElse и обязательно верните String, а затем trim,

    val someString = Option("some String  ")
    someString.getOrElse("").trim
    
  • если trimMe - это Column[String] класс вашего случая имеет trimMe: String, тогда просто оберните его в Option, затем getOrElse и затем trim:

    val str = "some other string  "
    Option(str).getOrElse("").trim
    

Таким образом, если это None или Some, исключение не генерируется.

(*) Не всегда могут быть запросы, которые возвращают столбцы, а не целые строки.

person Ende Neu    schedule 04.08.2014
comment
Я думаю, что моя проблема больше связана с тем, где именно и как это должно быть сделано в типичной архитектуре Play / Scala / Slick / JSON. Мне все еще не ясно из вашего ответа, как мне это делать. - person caprica; 04.08.2014
comment
Ваше правка указала мне на решение, спасибо. Я могу просто выполнить test.trimMe.getOrElse (). Trim. Я думал, что пробовал это раньше, но потом попробовал много разных способов ... - person caprica; 04.08.2014

как насчет простой логики с сопоставлением с образцом:

def trimOptionString(in: Option[String]): Option[String] = in.map(_.trim) match {
  case None => None
  case Some("") => None
  case Some(x) => Some(x)
}
person Roman Kazanovskyi    schedule 18.06.2018