Skip to content

Commit 89d0979

Browse files
authored
add ordering and rename query param to order_by for datasets (#33)
1 parent ade02b0 commit 89d0979

File tree

7 files changed

+76
-46
lines changed

7 files changed

+76
-46
lines changed

.scalafmt.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version = 3.5.2
1+
version = 3.5.8
22

33
runner.dialect = "scala213source3"
44

acdc-core/src/main/scala/com/salesforce/mce/acdc/db/DatasetQuery.scala

+21-9
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ import slick.jdbc.PostgresProfile.api._
1515

1616
object DatasetQuery {
1717

18-
object OrderColumn extends Enumeration {
18+
sealed trait OrderBy
19+
object OrderBy {
20+
case object CreatedAt extends OrderBy
21+
case object UpdatedAt extends OrderBy
22+
}
1923

20-
val CreatedAt = Value("created_at")
21-
val UpdatedAt = Value("updated_at")
24+
sealed trait Order
25+
object Order {
26+
case object Asc extends Order
27+
case object Desc extends Order
2228
}
2329

2430
def now() = LocalDateTime.now()
@@ -70,18 +76,24 @@ object DatasetQuery {
7076

7177
def filter(
7278
like: String,
73-
order: OrderColumn.Value,
79+
orderBy: OrderBy,
80+
order: Order,
7481
limit: Int,
7582
offset: Int
7683
): DBIO[Seq[DatasetTable.R]] = {
77-
val ordering = order match {
78-
case OrderColumn.CreatedAt => t: DatasetTable => t.createdAt
79-
case OrderColumn.UpdatedAt => t: DatasetTable => t.updatedAt
80-
case _ => throw new MatchError("unexpected order")
84+
val sortByColumn = (orderBy, order) match {
85+
case (OrderBy.CreatedAt, Order.Desc) =>
86+
t: DatasetTable => t.createdAt.desc
87+
case (OrderBy.CreatedAt, Order.Asc) =>
88+
t: DatasetTable => t.createdAt.asc
89+
case (OrderBy.UpdatedAt, Order.Desc) =>
90+
t: DatasetTable => t.updatedAt.desc
91+
case (OrderBy.UpdatedAt, Order.Asc) =>
92+
t: DatasetTable => t.updatedAt.asc
8193
}
8294
DatasetTable()
8395
.filter(_.name.like(s"$like"))
84-
.sortBy(ordering(_).desc)
96+
.sortBy(sortByColumn)
8597
.drop(offset)
8698
.take(limit)
8799
.result

acdc-ws/app/controllers/DatasetController.scala

+49-32
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import scala.concurrent.Future
1515
import play.api.libs.json.{JsError, JsNull, JsValue, Json}
1616
import play.api.mvc._
1717

18-
import com.salesforce.mce.acdc.db.DatasetQuery
19-
import com.salesforce.mce.acdc.db.DatasetTable
18+
import com.salesforce.mce.acdc.db.{DatasetQuery, DatasetTable}
2019
import models.CreateDatasetRequest
2120
import models.DatasetResponse
2221
import play.api.libs.json.JsString
@@ -90,47 +89,65 @@ class DatasetController @Inject() (
9089
case InvalidApiRequest(_) => Future.successful(Unauthorized(JsNull))
9190
}
9291

93-
def filter(like: String, order: Option[String], page: Option[Int], perPage: Option[Int]) =
94-
authAction.async {
95-
case ValidApiRequest(apiRole, _) =>
96-
val validated = for {
97-
vOrder <- DatasetController.validateOrder(order)
98-
vPage <- DatasetController.validateOne(page.getOrElse(1), "page")
99-
limit <- DatasetController.validateOne(perPage.getOrElse(50), "per_page")
100-
} yield (vOrder, limit, (vPage - 1) * limit)
101-
102-
validated match {
103-
case Right((o, limit, offset)) =>
104-
db.async(DatasetQuery.filter(like, o, limit, offset))
105-
.map(rs => Ok(Json.toJson(rs.map(toResponse))))
106-
case Left(msg) =>
107-
Future.successful(BadRequest(JsString(msg)))
108-
}
109-
110-
case InvalidApiRequest(_) =>
111-
Future.successful(Unauthorized(JsNull))
112-
}
92+
def filter(
93+
like: String,
94+
orderBy: Option[String],
95+
order: Option[String],
96+
page: Option[Int],
97+
perPage: Option[Int]
98+
) = authAction.async {
99+
case ValidApiRequest(apiRole, _) =>
100+
101+
val validated = for {
102+
vOrderBy <- DatasetController.validateOrderBy(orderBy)
103+
vOrder <- DatasetController.validateOrder(order)
104+
vPage <- DatasetController.validateOne(page.getOrElse(1), "page")
105+
limit <- DatasetController.validateOne(perPage.getOrElse(50), "per_page")
106+
} yield (vOrderBy, vOrder, limit, (vPage - 1) * limit)
107+
108+
validated match {
109+
case Right((by, ord, limit, offset)) =>
110+
db.async(DatasetQuery.filter(like, by, ord, limit, offset))
111+
.map(rs => Ok(Json.toJson(rs.map(toResponse))))
112+
case Left(msg) =>
113+
Future.successful(BadRequest(JsString(msg)))
114+
}
115+
116+
case InvalidApiRequest(_) =>
117+
Future.successful(Unauthorized(JsNull))
118+
}
113119

114120
}
115121

116122
object DatasetController {
117123

124+
private def validateOrderBy(
125+
orderBy: Option[String]
126+
): Either[String, DatasetQuery.OrderBy] = {
127+
orderBy
128+
.fold[Either[String, DatasetQuery.OrderBy]](
129+
Right(DatasetQuery.OrderBy.CreatedAt)
130+
) {
131+
case "created_at" => Right(DatasetQuery.OrderBy.CreatedAt)
132+
case "updated_at" => Right(DatasetQuery.OrderBy.UpdatedAt)
133+
case other => Left(s"Unknow order_by $other")
134+
}
135+
}
136+
118137
private def validateOrder(
119138
order: Option[String]
120-
): Either[String, DatasetQuery.OrderColumn.Value] = {
139+
): Either[String, DatasetQuery.Order] = {
121140
order
122-
.fold[Either[String, DatasetQuery.OrderColumn.Value]](
123-
Right(DatasetQuery.OrderColumn.CreatedAt)
124-
) { o =>
125-
try {
126-
Right(DatasetQuery.OrderColumn.withName(o))
127-
} catch {
128-
case e: NoSuchElementException =>
129-
Left(s"Unknow order $o")
130-
}
141+
.fold[Either[String, DatasetQuery.Order]](
142+
Right(DatasetQuery.Order.Desc)
143+
) {
144+
case "desc" => Right(DatasetQuery.Order.Desc)
145+
case "asc" => Right(DatasetQuery.Order.Asc)
146+
case other => Left(s"Unknow order $other")
131147
}
132148
}
133149

150+
134151
private def validateOne(num: Int, name: String): Either[String, Int] = {
135152
if (num < 1) Left(s"$name must be at least 1")
136153
else Right(num)

acdc-ws/app/routers/ApiRouter.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ class ApiRouter @Inject() (
2727
case GET(
2828
p"/datasets" ?
2929
q"like=$like" &
30+
q_o"order_by=$orderBy" &
3031
q_o"order=$order" &
3132
q_o"page=${int(page)}" &
3233
q_o"per_page=${int(perPage)}"
3334
) =>
34-
dataset.filter(like, order, page, perPage)
35+
dataset.filter(like, orderBy, order, page, perPage)
3536
case DELETE(p"/dataset/$name") => dataset.delete(name)
3637

3738
case POST(p"/instance") => instance.create()

build.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ lazy val core = (project in file("acdc-core")).
3535
libraryDependencies ++= Seq(
3636
"com.typesafe.slick" %% "slick" % slickVersion,
3737
"com.typesafe.slick" %% "slick-hikaricp" % slickVersion,
38-
"org.postgresql" % "postgresql" % "42.3.+",
38+
"org.postgresql" % "postgresql" % "42.4.+",
3939
)
4040
)
4141

project/plugins.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.0")
22

3-
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.15")
3+
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.16")
44

55
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
66

version.sbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ThisBuild / version := "0.6.3"
1+
ThisBuild / version := "0.7.0"

0 commit comments

Comments
 (0)