diff --git a/2.0/docs/json/overview.md b/2.0/docs/json/overview.md index 97473244..4e9efe54 100644 --- a/2.0/docs/json/overview.md +++ b/2.0/docs/json/overview.md @@ -67,7 +67,8 @@ extension User: JSONRepresentable { Now you can simply return `user.makeJSON()` in your routes. ```swift -drop.get("users", User.init) { req, user in +drop.get("users", User.parameter) { req in + let user = try req.parameters.next(User.self) return try user.makeJSON() } ``` @@ -82,7 +83,8 @@ extension User: ResponseRepresentable { } Now you can return the model by itself. It will automatically call `.makeJSON()`. ```swift -drop.get("users", User.init) { req, user in +drop.get("users", User.parameter) { req in + let user = try req.parameters.next(User.self) return try user } ``` diff --git a/2.0/docs/routing/controller.md b/2.0/docs/routing/controller.md deleted file mode 100644 index 5b84a208..00000000 --- a/2.0/docs/routing/controller.md +++ /dev/null @@ -1,76 +0,0 @@ -# Basic Controller - -Instead of defining all of your request handling logic as Closures in route files, you may wish to organize this behavior -using Controller classes. - -Controllers can group related request handling logic into a single class. They are normally stored -in the `Sources/App/Controllers` directory. - -## Defining Controllers - -```swift -import Vapor -import HTTP - -final class HelloController { - func sayHello(_ req: Request) throws -> ResponseRepresentable { - return "Hello" - } -} -``` - -You can define a route to this controller action like so: - -```swift -let controller = HelloController() -drop.get("hello", handler: controller.sayHello) -``` - -Now, when a request matches the specified route URI, the Index method on the FirstController -class will be executed. Of course, the route parameters will also be passed to the method. - -# Resource Controllers - -Vapor resource routing assigns the typical "CRUD" routes to a controller with a single line of code. - -```swift -drop.resource("users", UserController()) -``` - -This single route declaration creates multiple routes to handle a variety of actions on the resource. -The generated controller will already have methods stubbed for each of these actions, including -notes informing you of the HTTP verbs and URIs they handle. - -| Verb | URI | Action | -| :-------------: | :-------------: | :-----------: | -| GET | test/index | test.index | -| POST | test/create | test.create | -| GET | test/show | test.show | -| PUT | test/replace | test.replace | -| PATCH | test/destroy | test.destroy | -| DELETE | test/destroy | test.destroy | -| DELETE | test/clear | test.clear | - -You can also custom method name, add `makeResource` method in the controller - -```swift -final class UserController: ResourceRepresentable { - func index(_ req: Request) throws -> ResponseRepresentable { - ... - } - - ... - - func makeResource() -> Resource { - return Resource( - index: index, - store: create, - show: show, - replace: replace, - modify: update, - destroy: delete, - clear: clear - ) - } -} -``` diff --git a/2.0/docs/vapor/controllers.md b/2.0/docs/vapor/controllers.md index 9d788691..606f4de7 100644 --- a/2.0/docs/vapor/controllers.md +++ b/2.0/docs/vapor/controllers.md @@ -104,28 +104,9 @@ extension UserController: ResourceRepresentable { } ``` -Conforming `UserController` to `ResourceRepresentable` requires that the signatures of the `index` and `show` methods match what the `Resource` is expecting. +Conforming `UserController` to `ResourceRepresentable` requires that the signatures of +the `index` and `show` methods match what the `Resource` is expecting. -Here is a peek into the `Resource` class. - -```swift -final class Resource { - typealias Multiple = (Request) throws -> ResponseRepresentable - typealias Item = (Request, Model) throws -> ResponseRepresentable - - var index: Multiple? - var store: Multiple? - var show: Item? - var replace: Item? - var modify: Item? - var destroy: Item? - var clear: Multiple? - var aboutItem: Item? - var aboutMultiple: Multiple? - - ... -} -``` Now that `UserController` conforms to `ResourceRepresentable`, registering the routes is easy. @@ -139,6 +120,28 @@ drop.resource("users", users) !!! note `drop.resource` also adds useful defaults for OPTIONS requests. These can be overriden. +### Actions + +Below is a table describing all of the actions available. + +| Action | Method | Path | Note | +|---------|--------|-----------------|-------------------------------------------------------------------------------------------| +| index | GET | /users | Returns all users, optionally filtered by the request data. | +| store | POST | /users | Creates a new user from the request data. | +| show | GET | /users/:id | Returns the user with the ID supplied in the path. | +| replace | PUT | /users/:id | Updates the specified user, setting any fields not present in the request data to `nil`. | +| update | PATCH | /users/:id | Updates the specified user, only modifying fields present in the request data. | +| delete | DELETE | /users/:id | Deletes the specified user. | +| clear | DELETE | /users | Deletes all users, optionally filtered by the request data. | +| create | GET | /users/create | Displays a form for creating a new user. | +| edit | GET | /users/:id/edit | Displays a form for editing the specified user. | + +!!! tip + The difference between `replace` and `update` is subtle but important: + If a field does not exist in the request data (for example, the user's age is missing), + `update` should simply not update that field where as `replace` should set it to `nil`. + If required data is missing from a `replace` request, an error should be thrown. + ## Folder Controllers can go anywhere in your application, but they are most often stored in the `App/Controllers/` directory.