Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions documentation/manual/Migration23.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,47 @@ Moreover, erasure issues about parameter value is fixed: type is no longer `Para

Types for parameter names are also unified (when using `.on(...)`). Only `String` and `Symbol` are now supported as name.

Type *`Pk[A]`* has been deprecated. You can still use it as column mapping, but need to explicitly pass either `Id[A]` or `NotAssigned` as query parameter (as consequence of type safety improvements):

```scala
// Column mapping, deprecated but Ok
val pk: Pk[Long] = SQL("SELECT id FROM test WHERE name={n}").
on('n -> "mine").as(get[Pk[Long]].single)

// Wrong parameter
val pkParam: Pk[Long] = Id(1l)
val name1 = "Name #1"
SQL"INSERT INTO test(id, name) VALUES($pkParam, $name1)".execute()
// ... pkParam is passed as Pk in query parameter,
// which is now wrong as a parameter type (won't compile)

// Right parameter Id
val idParam: Id[Long] = Id(2l) // same as pkParam but keep explicit Id type
val name2 = "Name #2"
SQL"INSERT INTO test(id, name) VALUES($idParam, $name2)".execute()

// Right parameter NotAssigned
val name2 = "Name #3"
SQL"INSERT INTO test(id, name) VALUES($NotAssigned, $name2)".execute()
```

As deprecated `Pk[A]` is similar to `Option[A]`, which is supported by Anorm in column mapping and as query parameter, it's preferred to replace `Id[A]` by `Some[A]` and `NotAssigned` by `None`:

```scala
// Column mapping, deprecated but Ok
val pk: Option[Long] = SQL("SELECT id FROM test WHERE name={n}").
on('n -> "mine").as(get[Option[Long]].single)

// Assigned primary key as parameter
val idParam: Option[Long] = Some(2l)
val name1 = "Id"
SQL"INSERT INTO test(id, name) VALUES($idParam, $name1)".execute()

// Right parameter NotAssigned
val name2 = "NotAssigned"
SQL"INSERT INTO test(id, name) VALUES($None, $name2)".execute()
```

## Twitter Bootstrap

The in-built Twitter Bootstrap field constructor has been deprecated, and will be removed in a future version of Play.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object Application extends Controller {
*/
val computerForm = Form(
mapping(
"id" -> ignored(NotAssigned:Pk[Long]),
"id" -> ignored(None:Option[Long]),
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update related code samples

"name" -> nonEmptyText,
"introduced" -> optional(date("yyyy-MM-dd")),
"discontinued" -> optional(date("yyyy-MM-dd")),
Expand Down
13 changes: 8 additions & 5 deletions samples/scala/computer-database/app/models/Models.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import anorm.SqlParser._

import scala.language.postfixOps

case class Company(id: Pk[Long] = NotAssigned, name: String)
case class Computer(id: Pk[Long] = NotAssigned, name: String, introduced: Option[Date], discontinued: Option[Date], companyId: Option[Long])
case class Company(id: Option[Long] = None, name: String)
case class Computer(id: Option[Long] = None, name: String, introduced: Option[Date], discontinued: Option[Date], companyId: Option[Long])

/**
* Helper for pagination.
Expand All @@ -29,7 +29,7 @@ object Computer {
* Parse a Computer from a ResultSet
*/
val simple = {
get[Pk[Long]]("computer.id") ~
get[Option[Long]]("computer.id") ~
get[String]("computer.name") ~
get[Option[Date]]("computer.introduced") ~
get[Option[Date]]("computer.discontinued") ~
Expand Down Expand Up @@ -167,7 +167,7 @@ object Company {
* Parse a Company from a ResultSet
*/
val simple = {
get[Pk[Long]]("company.id") ~
get[Option[Long]]("company.id") ~
get[String]("company.name") map {
case id~name => Company(id, name)
}
Expand All @@ -177,7 +177,10 @@ object Company {
* Construct the Map[String,String] needed to fill a select options set.
*/
def options: Seq[(String,String)] = DB.withConnection { implicit connection =>
SQL("select * from company order by name").as(Company.simple *).map(c => c.id.toString -> c.name)
SQL("select * from company order by name").as(Company.simple *).
foldLeft[Seq[(String, String)]](Nil) { (cs, c) =>
c.id.fold(cs) { id => cs :+ (id.toString -> c.name) }
}
}

}
Expand Down
36 changes: 18 additions & 18 deletions samples/scala/zentasks/app/Global.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,32 @@ object InitialData {
).foreach(User.create)

Seq(
Project(Id(1), "Play framework", "Play 2.0") -> Seq("guillaume@sample.com", "maxime@sample.com", "sadek@sample.com", "erwan@sample.com"),
Project(Id(2), "Play framework", "Play 1.2.4") -> Seq("guillaume@sample.com", "erwan@sample.com"),
Project(Id(3), "Play framework", "Website") -> Seq("guillaume@sample.com", "maxime@sample.com"),
Project(Id(4), "Zenexity", "Secret project") -> Seq("guillaume@sample.com", "maxime@sample.com", "sadek@sample.com", "erwan@sample.com"),
Project(Id(5), "Zenexity", "Playmate") -> Seq("maxime@sample.com"),
Project(Id(6), "Personal", "Things to do") -> Seq("guillaume@sample.com"),
Project(Id(7), "Zenexity", "Play samples") -> Seq("guillaume@sample.com", "maxime@sample.com"),
Project(Id(8), "Personal", "Private") -> Seq("maxime@sample.com"),
Project(Id(9), "Personal", "Private") -> Seq("guillaume@sample.com"),
Project(Id(10), "Personal", "Private") -> Seq("erwan@sample.com"),
Project(Id(11), "Personal", "Private") -> Seq("sadek@sample.com")
Project(Some(1), "Play framework", "Play 2.0") -> Seq("guillaume@sample.com", "maxime@sample.com", "sadek@sample.com", "erwan@sample.com"),
Project(Some(2), "Play framework", "Play 1.2.4") -> Seq("guillaume@sample.com", "erwan@sample.com"),
Project(Some(3), "Play framework", "Website") -> Seq("guillaume@sample.com", "maxime@sample.com"),
Project(Some(4), "Zenexity", "Secret project") -> Seq("guillaume@sample.com", "maxime@sample.com", "sadek@sample.com", "erwan@sample.com"),
Project(Some(5), "Zenexity", "Playmate") -> Seq("maxime@sample.com"),
Project(Some(6), "Personal", "Things to do") -> Seq("guillaume@sample.com"),
Project(Some(7), "Zenexity", "Play samples") -> Seq("guillaume@sample.com", "maxime@sample.com"),
Project(Some(8), "Personal", "Private") -> Seq("maxime@sample.com"),
Project(Some(9), "Personal", "Private") -> Seq("guillaume@sample.com"),
Project(Some(10), "Personal", "Private") -> Seq("erwan@sample.com"),
Project(Some(11), "Personal", "Private") -> Seq("sadek@sample.com")
).foreach {
case (project,members) => Project.create(project, members)
}

Seq(
Task(NotAssigned, "Todo", 1, "Fix the documentation", false, None, Some("guillaume@sample.com")),
Task(NotAssigned, "Urgent", 1, "Prepare the beta release", false, Some(date("2011-11-15")), None),
Task(NotAssigned, "Todo", 9, "Buy some milk", false, None, None),
Task(NotAssigned, "Todo", 2, "Check 1.2.4-RC2", false, Some(date("2011-11-18")), Some("guillaume@sample.com")),
Task(NotAssigned, "Todo", 7, "Finish zentask integration", true, Some(date("2011-11-15")), Some("maxime@sample.com")),
Task(NotAssigned, "Todo", 4, "Release the secret project", false, Some(date("2012-01-01")), Some("sadek@sample.com"))
Task(None, "Todo", 1, "Fix the documentation", false, None, Some("guillaume@sample.com")),
Task(None, "Urgent", 1, "Prepare the beta release", false, Some(date("2011-11-15")), None),
Task(None, "Todo", 9, "Buy some milk", false, None, None),
Task(None, "Todo", 2, "Check 1.2.4-RC2", false, Some(date("2011-11-18")), Some("guillaume@sample.com")),
Task(None, "Todo", 7, "Finish zentask integration", true, Some(date("2011-11-15")), Some("maxime@sample.com")),
Task(None, "Todo", 4, "Release the secret project", false, Some(date("2012-01-01")), Some("sadek@sample.com"))
).foreach(Task.create)

}

}

}
}
2 changes: 1 addition & 1 deletion samples/scala/zentasks/app/controllers/Projects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object Projects extends Controller with Secured {
folder => Ok(
views.html.projects.item(
Project.create(
Project(NotAssigned, folder, "New project"),
Project(None, folder, "New project"),
Seq(username)
)
)
Expand Down
2 changes: 1 addition & 1 deletion samples/scala/zentasks/app/controllers/Tasks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ object Tasks extends Controller with Secured {
{
case (title, dueDate, assignedTo) =>
val task = Task.create(
Task(NotAssigned, folder, project, title, false, dueDate, assignedTo)
Task(None, folder, project, title, false, dueDate, assignedTo)
)
Ok(html.tasks.item(task))
}
Expand Down
6 changes: 3 additions & 3 deletions samples/scala/zentasks/app/models/Project.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import anorm.SqlParser._

import scala.language.postfixOps

case class Project(id: Pk[Long], folder: String, name: String)
case class Project(id: Option[Long], folder: String, name: String)

object Project {

Expand All @@ -18,7 +18,7 @@ object Project {
* Parse a Project from a ResultSet
*/
val simple = {
get[Pk[Long]]("project.id") ~
get[Option[Long]]("project.id") ~
get[String]("project.folder") ~
get[String]("project.name") map {
case id~folder~name => Project(id, folder, name)
Expand Down Expand Up @@ -187,7 +187,7 @@ object Project {
SQL("insert into project_member values ({id}, {email})").on("id" -> id, "email" -> email).executeUpdate()
}

project.copy(id = Id(id))
project.copy(id = Some(id))

}
}
Expand Down
6 changes: 3 additions & 3 deletions samples/scala/zentasks/app/models/Task.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import anorm.SqlParser._

import scala.language.postfixOps

case class Task(id: Pk[Long], folder: String, project: Long, title: String, done: Boolean, dueDate: Option[Date], assignedTo: Option[String])
case class Task(id: Option[Long], folder: String, project: Long, title: String, done: Boolean, dueDate: Option[Date], assignedTo: Option[String])

object Task {

Expand All @@ -20,7 +20,7 @@ object Task {
* Parse a Task from a ResultSet
*/
val simple = {
get[Pk[Long]]("task.id") ~
get[Option[Long]]("task.id") ~
get[String]("task.folder") ~
get[Long]("task.project") ~
get[String]("task.title") ~
Expand Down Expand Up @@ -173,7 +173,7 @@ object Task {
"assignedTo" -> task.assignedTo
).executeUpdate()

task.copy(id = Id(id))
task.copy(id = Some(id))

}
}
Expand Down