2013-02-20 32 views
14

Vì vậy, trong Chơi 2.0 Tôi có điều này:đường với tham số tùy chọn - Chơi 2.1 Scala

GET  /tasks/add    controllers.Tasks.addTask(parentId: Option[Long] = None) 
GET  /tasks/:parentId/add controllers.Tasks.addTask(parentId: Option[Long]) 

Với một phương pháp điều khiển như thế này:

def addTask(parentId: Option[Long]) = Action { 
    Ok(views.html.addTask(taskForm, parentId)) 
} 

Và nó đã làm việc. Khi tôi di chuyển sang 2.1, có vẻ như khiếu nại về những dòng này: No URL path binder found for type Option[Long]. Try to implement an implicit PathBindable for this type. Về cơ bản, những gì tôi đang cố gắng hoàn thành là có tuyến đường tasks/add và tuyến đường tasks/123/add liên kết đến cùng một phương thức chấp nhận Optional[Long]. Bất kỳ ý tưởng làm thế nào để làm điều này? Cảm ơn. Ok, vì vậy tôi đã nhận được một loại nó không phải là một lỗi, nó là một phản ứng tính năng trên Lighthouse: "Chúng tôi đã xóa tùy chọn [Long] hỗ trợ trong đường dẫn bindables vì ​​nó không có ý nghĩa để có một tham số đường dẫn tùy chọn. có thể thực hiện đường dẫn của riêng bạn có thể ràng buộc hỗ trợ nó nếu bạn muốn. " Cho đến nay tôi có 2 giải pháp, đi qua -1 như parentId, mà tôi không thực sự thích. Hoặc có 2 phương pháp khác nhau, có thể có ý nghĩa hơn trong trường hợp này. Việc triển khai PathBindable dường như không khả thi lắm, vì vậy tôi có thể sẽ có 2 phương thức.

Trả lời

13

Chơi 2.0 hỗ trợ Option trong các tham số đường, Play 2.1 không còn hỗ trợ điều này, họ loại bỏ PathBindable cho Option.

Một giải pháp khả thi sẽ là:

package extensions 
import play.api.mvc._ 
object Binders { 
    implicit def OptionBindable[T : PathBindable] = new PathBindable[Option[T]] { 
    def bind(key: String, value: String): Either[String, Option[T]] = 
     implicitly[PathBindable[T]]. 
     bind(key, value). 
     fold(
      left => Left(left), 
      right => Right(Some(right)) 
     ) 

    def unbind(key: String, value: Option[T]): String = value map (_.toString) getOrElse "" 
    } 
} 

Và thêm video này vào Build.scala sử dụng routesImport += "extensions.Binders._". Chạy play clean ~run và nó sẽ hoạt động. Tải lại các Chất kết dính khi đang bay đôi khi chỉ hoạt động.

+0

Cảm ơn, tôi đã báo cáo. Bạn có bất kỳ ý tưởng làm thế nào để có được những hành vi mong muốn mà không cần phải chờ đợi một bugfix? – Laky

+2

Ok, vì vậy: "Chúng tôi đã xóa tùy chọn [Long] hỗ trợ trong đường dẫn ràng buộc vì không có ý nghĩa để có tham số đường dẫn tùy chọn. Bạn có thể triển khai đường dẫn của riêng bạn có thể ràng buộc hỗ trợ nó nếu bạn muốn." Nhưng đi qua một tùy chọn thay vì một số giá trị tùy ý dường như với tôi rất nhiều đẹp hơn. Đó không phải là lý do chúng ta có tùy chọn ở nơi đầu tiên sao? Có lẽ tôi sẽ tạo ra 2 phương pháp khác nhau trong trường hợp này, vì nó sẽ có ý nghĩa hơn so với truyền -1 là id. – Laky

+4

Có bạn đúng, điều đó tốt hơn nhiều. Tuy nhiên, tôi không hiểu quyết định của họ, tại sao xóa nội dung nào đó cho phép các URL đẹp hơn? –

5

Tôi nghĩ rằng bạn cần phải thêm một dấu chấm hỏi:

controllers.Tasks.addTask(parentId: Option[Long] ?= None)

+2

Không đó chỉ cho tham số truy vấn, chứ không phải cho các bộ phận của con đường. –

+0

@Marius làm cho một điểm tốt, nhưng 1 anyway, bởi vì bạn trả lời câu hỏi được đưa ra trong tiêu đề: "Tuyến đường với tham số tùy chọn" –

5

Từ routes-with-optional-parameter này đề nghị đi như thế:

GET /     controllers.Application.show(page = "home") 
GET /:page    controllers.Application.show(page) 
+4

Tôi biết về điều này, tuy nhiên, tôi muốn nhận được xung quanh phải vượt qua một giá trị mặc định. Tham số phải chứa id hoặc không có gì. Tôi có thể vượt qua -1 hoặc một cái gì đó tương tự như chỉ ra phần không có gì, nhưng tôi muốn sử dụng Option cho điều đó, vì nó có vẻ đẹp hơn rất nhiều với tôi. – Laky

+0

Điều gì xảy ra nếu tôi muốn tính tham số mặc định khi chạy? Tôi nên sử dụng cái gì làm chữ cho tham số mặc định? –

+0

Tôi không thể sử dụng kỹ thuật này. Tôi nhận được http 500. Tôi đang sử dụng POST. POST/copy /: param1 /: param2 @ controllers.MyController.copy (param1, param2) POST/copy /: param2 @ controllers.MyController.copy (param1 = "", param2). Yêu cầu bài đăng được thực hiện là "/ copy/somestring" – Skychan

0

tôi đã điều tương tự và nhiều hơn nữa nếu bạn chỉ định đường chuyền như GET/foo:idcontrollers.Application.foo(id : Option[Long] ?= None) bạn nhận được một lỗi It is not allowed to specify a fixed or default value for parameter: 'id' extracted from the path ở phía bên kia bạn có thể làm như sau GET/foo controllers.Application.foo(id : Option[Long] ?= None) và nó sẽ làm việc mong rằng yêu cầu của bạn trông giống như .../foo?id=1

2

Các giải pháp đơn giản cho vấn đề của bạn, mà không cần phải vượt qua một giá trị mặc định, là thêm một phương pháp proxy đơn giản kết thúc tốt đẹp các tham số trong một tùy chọn.

Tuyến đường:

GET  /tasks/add    controllers.Tasks.addTask() 
GET  /tasks/:parentId/add controllers.Tasks.addTaskProxy(parentId: Long) 

Bộ điều khiển:

def addTask(parentId: Option[Long] = None) = Action { 
    Ok(views.html.addTask(taskForm, parentId)) 
} 

def addTaskProxy(parentId: Long) = addTask(Some(parentId)) 
+0

Một cách giải quyết, vẫn còn khó chịu Tôi nghĩ – Sorona

Các vấn đề liên quan