Hi I want to update only one value of an model and store it to database.
I try this:
def updateProcessTemplateApproveProcessId(processTemplate: ProcessTemplatesModel, approveProcessInstanceId: Int): Future[Int] = {
val action = for {
processTemplatesUpdate <- processTemplates if processTemplatesUpdate.id === processTemplate.id // WHERE Statement
} yield processTemplatesUpdate.approveProcessInstance = Some(approveProcessInstanceId) // SELECT Statement
db.run(action.update(Some(true)))
}
But I got error reassignment to val is not allowed ... thats correct ;) so I changed the attribute in model to var.
case class ProcessTemplatesModel(
id: Option[Int] = None,
title: String,
version: String,
createdat: Option[String],
updatedat: Option[String],
deadline: Option[Date],
status: Option[String],
comment: Option[String],
checked: Option[Boolean],
checkedat: Option[Date],
approved: Option[Boolean],
approvedat: Option[Date],
deleted: Boolean,
approveprocess: Int,
trainingsprocess: Option[Int],
previousVersion: Option[Int],
originTemplate: Option[Int],
client: Int,
var approveProcessInstance: Option[Int],
Whats my fil in this case?
Thanks in advance
Don't change your case class. Assuming that processTemplates is a TableQuery, do the following instead:
val query = for {
processTemplatesUpdate <- processTemplates if processTemplatesUpdate.id === processTemplate.id
} yield processTemplatesUpdate.approveProcessInstance
val action = query.update(Some(approveProcessInstanceId))
db.run(action)
If you want one liner (Assuming that processTemplates is a TableQuery object)
db.run(processTemplates.filter(_.id === processTemplate.id).map(_. approveProcessInstanceId).update(Some(true)))
Hope this helps.
Related
I'm trying to use Spray JSON to marshall the 'Seq' collection below into a 'BidRequest' entity with the parameters as defined.
The Seq collection is mostly nested, therefore some 'Seq' parameter fields also have variable collection types that need to be marshalled.
Then after a computation, the aim is to unmarshall the results as an entity of 'BidResponse'.
What's the best approach to do this?
I'm using Akka-HTTP, Akka-Streams, Akka-Actor.
Seq collection:
val activeUsers = Seq(
Campaign(
id = 1,
country = "UK",
targeting = Targeting(
targetedSiteIds = Seq("0006a522ce0f4bbbbaa6b3c38cafaa0f")
),
banners = List(
Banner(
id = 1,
src ="https://business.URLTV.com/wp-content/uploads/2020/06/openGraph.jpeg",
width = 300,
height = 250
)
),
bid = 5d
)
)
BidRequest case class:
case class BidRequest(id: String, imp: Option[List[Impression]], site:Site, user: Option[User], device: Option[Device])
BidResponse case class:
case class BidResponse(id: String, bidRequestId: String, price: Double, adid:Option[String], banner: Option[Banner])
The other case classes:
case class Campaign(id: Int, country: String, targeting: Targeting, banners: List[Banner], bid: Double)
case class Targeting(targetedSiteIds: Seq[String])
case class Banner(id: Int, src: String, width: Int, height: Int)
case class Impression(id: String, wmin: Option[Int], wmax: Option[Int], w: Option[Int], hmin: Option[Int], hmax: Option[Int], h: Option[Int], bidFloor: Option[Double])
case class Site(id: Int, domain: String)
case class User(id: String, geo: Option[Geo])
case class Device(id: String, geo: Option[Geo])
case class Geo(country: Option[String])
I've so far tried using the code below but keep getting type mismatch errors:
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._
implicit val resFormat = jsonFormat2(BidResponse)
implicit val bidFormat = jsonFormat1(BidRequest)
implicit val cFormat = jsonFormat1(Campaign)
implicit val tFormat = jsonFormat1(Targeting)
implicit val bFormat = jsonFormat1(Banner)
implicit val iFormat = jsonFormat1(Impression)
implicit val sFormat = jsonFormat1(Site)
implicit val uFormat = jsonFormat1(User)
implicit val dFormat = jsonFormat1(Device)
implicit val gFormat = jsonFormat1(Geo)
The reason why you are getting Type errors with Spray JSON is because you need to use the corresponding jsonFormatN method, depending on the number of parameters in the case class.
In your case:
implicit val resFormat = jsonFormat5(BidResponse)
implicit val bidFormat = jsonFormat5(BidRequest)
implicit val cFormat = jsonFormat1(Campaign)
implicit val tFormat = jsonFormat1(Targeting)
implicit val bFormat = jsonFormat4(Banner)
...
I am trying to write some REST API to fetch the data using Scala Slick 3.2.3. Is there a way to calculate a derived column and include it in the returned output?
My model:
case class Task(id: Option[TaskId], title: String, dueOn: String, status: String, createdAt: String, updatedAt: String)
Table class:
class TasksTable(tag: Tag) extends Table[Task](tag, _tableName = "TASKS") {
def id: Rep[TaskId] = column[TaskId]("ID", O.PrimaryKey, O.AutoInc)
def title: Rep[String] = column[String]("TITLE")
def dueOn: Rep[String] = column[String]("DUE_ON")
def status: Rep[String] = column[String]("STATUS")
def createdAt: Rep[String] = column[String]("CREATED_AT")
def updatedAt: Rep[String] = column[String]("UPDATED_AT")
def * = (id.?, title, dueOn, status, createdAt, updatedAt) <> ((Task.apply _).tupled, Task.unapply)
}
DAO:
object TasksDao extends BaseDao {
def findAll: Future[Seq[Task]] = tasksTable.result
}
I want to add a column in the response json called timeline with values "overdue", "today", "tomorrow", "upcoming", etc. calculated based on the dueOn value.
I tried searching but could not find any help. Any help with an example or any pointers would be highly appreciated. Thanks!
First I'd start from defining enum model for timeline:
object Timelines extends Enumeration {
type Timeline = Value
val Overdue: Timeline = Value("overdue")
val Today: Timeline = Value("today")
val Tomorrow: Timeline = Value("tomorrow")
val Upcoming: Timeline = Value("upcoming")
}
Then I'd modify dueOne column type from plain String to LocalDate - this will be easier to do on DAO level, so Slick will handle parsing errors for us.
So, to need to define custom type for LocalDate (see for more details: http://scala-slick.org/doc/3.0.0/userdefined.html#using-custom-scalar-types-in-queries).
// Define mapping between String and LocalDate
private val defaultDateFormat: DateTimeFormatter = DateTimeFormatter.ISO_DATE // replace it with formatter you use for a date
def stringDateColumnType(format: DateTimeFormatter): BaseColumnType[LocalDate] = {
MappedColumnType.base[LocalDate, String](_.format(format), LocalDate.parse(_, format))
}
implicit val defaultStringDateColumnType: BaseColumnType[LocalDate] = stringDateColumnType(defaultDateFormat)
private val defaultDateFormat: DateTimeFormatter = DateTimeFormatter.ISO_DATE // replace it with formatter you use for a date
// Change `dueOn` from String to LocalDate
case class Task(id: Option[TaskId], title: String, dueOn: LocalDate, status: String, createdAt: String, updatedAt: String)
class TasksTable(tag: Tag) extends Table[Task](tag, _tableName = "TASKS") {
def id: Rep[TaskId] = column[TaskId]("ID", O.PrimaryKey, O.AutoInc)
def title: Rep[String] = column[String]("TITLE")
def dueOn: Rep[LocalDate] = column[LocalDate]("DUE_ON") // Then replace column type
def status: Rep[String] = column[String]("STATUS")
def createdAt: Rep[String] = column[String]("CREATED_AT")
def updatedAt: Rep[String] = column[String]("UPDATED_AT")
def * = (id.?, title, dueOn, status, createdAt, updatedAt) <> ((Task.apply _).tupled, Task.unapply)
}
Then define API level model TaskResponse with new additional timeline field:
case class TaskResponse(id: Option[TaskId], title: String, dueOn: LocalDate, status: String, createdAt: String, updatedAt: String, timeline: Timeline)
object TaskResponse {
import Timelines._
def fromTask(task: Task): TaskResponse = {
val timeline = dueOnToTimeline(task.dueOn)
TaskResponse(task.id, task.title, task.dueOn, task.status, task.createdAt, task.updatedAt, timeline)
}
def dueOnToTimeline(dueOn: LocalDate): Timeline = {
val today = LocalDate.now()
Period.between(today, dueOn).getDays match {
case days if days < 0 => Overdue
case 0 => Today
case 1 => Tomorrow
case _ => Upcoming
}
}
}
Then you can create TasksService responsible for business logic of converting:
class TasksService(dao: TasksDao)(implicit ec: ExecutionContext) {
def findAll: Future[Seq[TaskResponse]] = {
dao.findAll.map(_.map(TaskResponse.fromTask))
}
}
Hope this helps!
case class Employee(name :String, dept :String, empId:String, startDate:String)
val emp1 = Employee("abc","accounts", "1234","2019-09-28")
val emp2 = Employee("def","HR", "12345","2019-09-29")
val emp3 = Employee("pp","HR", "12346", "2019-09-28")
val emp4 = Employee("xyz","accounts", "12347","2019-09-20")
val list = Seq(emp1, emp2, emp3, emp4)
def isValidDate(date: LocalDateTime, e:
Employee):Boolean={
date.isAfter(e.startDate)
}
private def test(name :String, date:String,list:Seq[Employee])={
list.exists(e =>isValidDate(LocalDate.parse(date).atStartOfDay(), e))
}
test("abc",2019-09-28, list)
test("xyz",2019-09-28, list)
test("def",2019-09-28, list)
The above works but when I change method to below
def isValidDate(date: LocalDateTime, e:
Employee):Try[Boolean]={
date.isAfter(e.startDate)
}
The below line gives compile error as it expects a boolean
list.exists(e =>isValidDate(date, e))
I want the handling of success and failure be outside isValidDate method
First of all, you'll need to change the implementation of isValidDate:
def isValidDate(date: LocalDateTime, e: Employee): Try[Boolean]={
Try { date.isAfter(e.startDate) }
}
Then, the implementation of your higher order function would need to deal with the Try:
private def test(name: String, date: LocalDateTime, list: Seq[Employee]) = {
list.exists(isValidDate(date, _) match {
case Failure(_) => false
case Success(value: Boolean) => value
})
}
Or as Zang proposes in the comments:
private def test(name: String, date: LocalDateTime, list: Seq[Employee]) = {
list.exists(isValidDate(date, _).getOrElse(false))
}
I would say though, that I'm not sure all this is necessary. Does isAfter throw any exception? Try is mostly used to capture exceptional code, which I don't think is the case here.
If you want to handle the exception outside isValidDate then there is no point in changing isValidDate, you can simply catch the exception outside. For example
private def test(name: String, date: LocalDateTime, list: Seq[Employee]) =
Try {
list.exists(e => isValidDate(date, e))
}.getOrElse(false)
This will fail the whole test if there is an exception. If you want to ignore exceptions and keep testing later employees, do this
private def test(name: String, date: LocalDateTime, list: Seq[Employee]) =
list.exists(e => Try(isValidDate(date, e)).getOrElse(false))
However in this case I believe that it better to put the exception handling in isValidDate, even though this is not what you say you want:
def isValidDate(date: LocalDateTime, e: Employee): Boolean =
Try(date.isAfter(e.startDate)).getOrElse(false)
private def test(name: String, date: LocalDateTime, list: Seq[Employee]) =
list.exists(e => isValidDate(date, e))
I am using dse 5.1.0 (packaged with spark 2.0.2.6 and scala 2.11.8).
reading a cassandra table as below.
val sparkSession = ...
val rdd1 = sparkSession.table("keyspace.table")
This table contains a List[String] column, say list1, which I read in scala rdd, say rdd1. But when I try to use encoder, it throws error.
val myVoEncoder = Encoders.bean(classOf[myVo])
val dataSet = rdd1.as(myVoEncoder)
I have tried with
scala.collection.mutable.list,
scala.collection.immutable.list,
scala.collection.list,
Seq,
WrappedArray. All gave the same error as below.
java.lang.UnsupportedOperationException: Cannot infer type for class scala.collection.immutable.List because it is not bean-compliant
MyVo.scala
case class MyVo(
#BeanProperty var id: String,
#BeanProperty var duration: Int,
#BeanProperty var list1: List[String],
) {
def this() = this("", 0, null)
}
Any help will be appriciated.
You should use Array[String]:
case class MyVo(
#BeanProperty var id: String,
#BeanProperty var duration: Int,
#BeanProperty var list1: Array[String]
) {
def this() = this("", 0, null)
}
although it is important to stress out, that more idiomatic approach would be:
import sparkSession.implicits._
case class MyVo(
id: String,
duration: Int,
list1: Seq[String]
)
rdd1.as[MyVo]
Suppose I have a normalized database model for a generic type that comes in like this:
case class BaseModel(id: String,
createdBy: String,
attr1: Option[String] = None,
attr2: Option[Int] = None,
attr3: Option[LocalDate] = None)
Given a sequence of BaseModel, if all the fields of a certain Option attribute are not populated, can shapeless create a reduced model for me?
For example suppose that all the attr1 fields are empty. Without me having to specify the object before hand can shapeless create a generic object that looks like this?
case class BaseModel(id: String,
createdBy: String,
attr2: Option[Int] = None,
attr3: Option[LocalDate] = None)
What Shapeless can do is, given two case classes, create an object of one of them from an object of another.
import java.time.LocalDate
import shapeless.LabelledGeneric
import shapeless.record._
case class BaseModel(id: String,
createdBy: String,
attr1: Option[String] = None,
attr2: Option[Int] = None,
attr3: Option[LocalDate] = None)
case class BaseModel1(id: String,
createdBy: String,
attr2: Option[Int] = None,
attr3: Option[LocalDate] = None)
val bm = BaseModel(
id = "cff4545gvgf",
createdBy = "John Doe",
attr2 = Some(42),
attr3 = Some(LocalDate.parse("2018-11-03"))
) // BaseModel(cff4545gvgf,John Doe,None,Some(42),Some(2018-11-03))
val hlist = LabelledGeneric[BaseModel].to(bm)
val hlist1 = hlist - 'attr1
val bm1 = LabelledGeneric[BaseModel1].from(hlist1)
// BaseModel1(cff4545gvgf,John Doe,Some(42),Some(2018-11-03))
But Shapeless can't create a new case class. If you need a new case class to be created automatically you can write a macro.