diff --git a/build/2.0/json/overview/index.html b/build/2.0/json/overview/index.html index 7bd9f1ef..f2580b29 100644 --- a/build/2.0/json/overview/index.html +++ b/build/2.0/json/overview/index.html @@ -1748,7 +1748,8 @@

Now you can simply return user.makeJSON() in your routes.

-
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()
 }
 
@@ -1761,7 +1762,8 @@ you will get the conformance for free.

Now you can return the model by itself. It will automatically call .makeJSON().

-
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/build/2.0/mkdocs/search_index.json b/build/2.0/mkdocs/search_index.json index 78cf23ec..c4948101 100644 --- a/build/2.0/mkdocs/search_index.json +++ b/build/2.0/mkdocs/search_index.json @@ -497,7 +497,7 @@ }, { "location": "/vapor/controllers/", - "text": "Controllers\n\n\nControllers help you organize related functionality into a single place. They can also be used to create RESTful resources.\n\n\nBasic\n\n\nA basic controller looks like the following:\n\n\nimport\n \nVapor\n\n\nimport\n \nHTTP\n\n\n\nfinal\n \nclass\n \nHelloController\n \n{\n\n \nfunc\n \nsayHello\n(\n_\n \nreq\n:\n \nRequest\n)\n \nthrows\n \n-\n \nResponseRepresentable\n \n{\n\n \nguard\n \nlet\n \nname\n \n=\n \nreq\n.\ndata\n[\nname\n]?.\nstring\n \nelse\n \n{\n \n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n\n \nreturn\n \nHello, \n\\(\nname\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nSimple controllers don't need to conform to any protocols. You are free to design them however you see fit.\n\n\nRegistering\n\n\nThe only required structure is the signature of each method in the controller. In order to register this method into the router, it must have a signature like \n(Request) throws -\n ResponseRepresentable\n. \nRequest\n and \nResponseRepresentable\n are made available by importing the \nHTTP\n module.\n\n\nimport\n \nVapor\n\n\nlet\n \ndrop\n \n=\n \ntry\n \nDroplet\n()\n\n\n\nlet\n \nhc\n \n=\n \nHelloController\n()\n\n\ndrop\n.\nget\n(\nhello\n,\n \nhandler\n:\n \nhc\n.\nsayHello\n)\n\n\n\n\n\n\nSince the signature of our \nsayHello\n method matches the signature of the closure for the \ndrop.get\n method, we can pass it directly.\n\n\nType Safe\n\n\nYou can also use controller methods with type-safe routing.\n\n\nfinal\n \nclass\n \nHelloController\n \n{\n\n \n...\n\n\n \nfunc\n \nsayHelloAlternate\n(\n_\n \nreq\n:\n \nRequest\n)\n \n-\n \nResponseRepresentable\n \n{\n\n \nlet\n \nname\n:\n \nString\n \n=\n \ntry\n \nreq\n.\nparameters\n.\nnext\n(\nString\n.\nself\n)\n\n \nreturn\n \nHello, \n\\(\nname\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nWe add a new method called \nsayHelloAlternate\n to the \nHelloController\n that fetches a \nString\n from the request's parameters.\n\n\nlet\n \nhc\n \n=\n \nHelloController\n()\n\n\ndrop\n.\nget\n(\nhello\n,\n \nString\n.\nparameter\n,\n \nhandler\n:\n \nhc\n.\nsayHelloAlternate\n)\n\n\n\n\n\n\nSince \ndrop.get\n accepts a signature \n(Request) throws -\n ResponseRepresentable\n, our method can now be used as the closure for this route. \n\n\n\n\nNote\n\n\nRead more about type safe routing in the \nRouting Parameters\n section.\n\n\n\n\nResources\n\n\nControllers that conform to \nResourceRepresentable\n can be easily registered into a router as a RESTful resource. Let's look at an example of a \nUserController\n.\n\n\nfinal\n \nclass\n \nUserController\n \n{\n\n \nfunc\n \nindex\n(\n_\n \nreq\n:\n \nRequest\n)\n \nthrows\n \n-\n \nResponseRepresentable\n \n{\n\n \nreturn\n \ntry\n \nUser\n.\nall\n().\nmakeJSON\n()\n\n \n}\n\n\n \nfunc\n \nshow\n(\n_\n \nreq\n:\n \nRequest\n)\n \n-\n \nResponseRepresentable\n \n{\n\n \nlet\n \nuser\n \n=\n \ntry\n \nreq\n.\nparameters\n.\nnext\n(\nUser\n.\nself\n)\n\n \nreturn\n \nuser\n\n \n}\n\n\n}\n\n\n\n\n\n\nHere is a typical user controller with an \nindex\n and \nshow\n route. Indexing returns a JSON list of all users and showing returns a JSON representation of a single user.\n\n\nWe \ncould\n register the controller like so:\n\n\nlet\n \nusers\n \n=\n \nUserController\n()\n\n\ndrop\n.\nget\n(\nusers\n,\n \nhandler\n:\n \nusers\n.\nindex\n)\n\n\ndrop\n.\nget\n(\nusers\n,\n \nUser\n.\nself\n,\n \nhandler\n:\n \nusers\n.\nshow\n)\n\n\n\n\n\n\nBut \nResourceRepresentable\n makes this standard RESTful structure easy.\n\n\nextension\n \nUserController\n:\n \nResourceRepresentable\n \n{\n\n \nfunc\n \nmakeResource\n()\n \n-\n \nResource\nUser\n \n{\n\n \nreturn\n \nResource\n(\n\n \nindex\n:\n \nindex\n,\n\n \nshow\n:\n \nshow\n\n \n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nConforming \nUserController\n to \nResourceRepresentable\n requires that the signatures of the \nindex\n and \nshow\n methods match what the \nResource\nUser\n is expecting.\n\n\nHere is a peek into the \nResource\n class.\n\n\nfinal\n \nclass\n \nResource\nModel\n:\n \nStringInitializable\n \n{\n\n \ntypealias\n \nMultiple\n \n=\n \n(\nRequest\n)\n \nthrows\n \n-\n \nResponseRepresentable\n\n \ntypealias\n \nItem\n \n=\n \n(\nRequest\n,\n \nModel\n)\n \nthrows\n \n-\n \nResponseRepresentable\n\n\n \nvar\n \nindex\n:\n \nMultiple\n?\n\n \nvar\n \nstore\n:\n \nMultiple\n?\n\n \nvar\n \nshow\n:\n \nItem\n?\n\n \nvar\n \nreplace\n:\n \nItem\n?\n\n \nvar\n \nmodify\n:\n \nItem\n?\n\n \nvar\n \ndestroy\n:\n \nItem\n?\n\n \nvar\n \nclear\n:\n \nMultiple\n?\n\n \nvar\n \naboutItem\n:\n \nItem\n?\n\n \nvar\n \naboutMultiple\n:\n \nMultiple\n?\n\n\n \n...\n\n\n}\n\n\n\n\n\n\nNow that \nUserController\n conforms to \nResourceRepresentable\n, registering the routes is easy.\n\n\nlet\n \nusers\n \n=\n \nUserController\n()\n\n\ndrop\n.\nresource\n(\nusers\n,\n \nusers\n)\n\n\n\n\n\n\ndrop.resource\n will take care of registering only the routes that have been supplied by the call to \nmakeResource()\n. In this case, only the \nindex\n and \nshow\n routes will be supplied.\n\n\n\n\nNote\n\n\ndrop.resource\n also adds useful defaults for OPTIONS requests. These can be overriden. \n\n\n\n\nFolder\n\n\nControllers can go anywhere in your application, but they are most often stored in the \nApp/Controllers/\n directory. \n\n\n\n\nTip\n\n\nIf you are building a large application, you may want to create your controllers in a separate module. This will allow you to perform unit tests on your controllers.", + "text": "Controllers\n\n\nControllers help you organize related functionality into a single place. They can also be used to create RESTful resources.\n\n\nBasic\n\n\nA basic controller looks like the following:\n\n\nimport\n \nVapor\n\n\nimport\n \nHTTP\n\n\n\nfinal\n \nclass\n \nHelloController\n \n{\n\n \nfunc\n \nsayHello\n(\n_\n \nreq\n:\n \nRequest\n)\n \nthrows\n \n-\n \nResponseRepresentable\n \n{\n\n \nguard\n \nlet\n \nname\n \n=\n \nreq\n.\ndata\n[\nname\n]?.\nstring\n \nelse\n \n{\n \n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n\n \nreturn\n \nHello, \n\\(\nname\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nSimple controllers don't need to conform to any protocols. You are free to design them however you see fit.\n\n\nRegistering\n\n\nThe only required structure is the signature of each method in the controller. In order to register this method into the router, it must have a signature like \n(Request) throws -\n ResponseRepresentable\n. \nRequest\n and \nResponseRepresentable\n are made available by importing the \nHTTP\n module.\n\n\nimport\n \nVapor\n\n\nlet\n \ndrop\n \n=\n \ntry\n \nDroplet\n()\n\n\n\nlet\n \nhc\n \n=\n \nHelloController\n()\n\n\ndrop\n.\nget\n(\nhello\n,\n \nhandler\n:\n \nhc\n.\nsayHello\n)\n\n\n\n\n\n\nSince the signature of our \nsayHello\n method matches the signature of the closure for the \ndrop.get\n method, we can pass it directly.\n\n\nType Safe\n\n\nYou can also use controller methods with type-safe routing.\n\n\nfinal\n \nclass\n \nHelloController\n \n{\n\n \n...\n\n\n \nfunc\n \nsayHelloAlternate\n(\n_\n \nreq\n:\n \nRequest\n)\n \n-\n \nResponseRepresentable\n \n{\n\n \nlet\n \nname\n:\n \nString\n \n=\n \ntry\n \nreq\n.\nparameters\n.\nnext\n(\nString\n.\nself\n)\n\n \nreturn\n \nHello, \n\\(\nname\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nWe add a new method called \nsayHelloAlternate\n to the \nHelloController\n that fetches a \nString\n from the request's parameters.\n\n\nlet\n \nhc\n \n=\n \nHelloController\n()\n\n\ndrop\n.\nget\n(\nhello\n,\n \nString\n.\nparameter\n,\n \nhandler\n:\n \nhc\n.\nsayHelloAlternate\n)\n\n\n\n\n\n\nSince \ndrop.get\n accepts a signature \n(Request) throws -\n ResponseRepresentable\n, our method can now be used as the closure for this route. \n\n\n\n\nNote\n\n\nRead more about type safe routing in the \nRouting Parameters\n section.\n\n\n\n\nResources\n\n\nControllers that conform to \nResourceRepresentable\n can be easily registered into a router as a RESTful resource. Let's look at an example of a \nUserController\n.\n\n\nfinal\n \nclass\n \nUserController\n \n{\n\n \nfunc\n \nindex\n(\n_\n \nreq\n:\n \nRequest\n)\n \nthrows\n \n-\n \nResponseRepresentable\n \n{\n\n \nreturn\n \ntry\n \nUser\n.\nall\n().\nmakeJSON\n()\n\n \n}\n\n\n \nfunc\n \nshow\n(\n_\n \nreq\n:\n \nRequest\n)\n \n-\n \nResponseRepresentable\n \n{\n\n \nlet\n \nuser\n \n=\n \ntry\n \nreq\n.\nparameters\n.\nnext\n(\nUser\n.\nself\n)\n\n \nreturn\n \nuser\n\n \n}\n\n\n}\n\n\n\n\n\n\nHere is a typical user controller with an \nindex\n and \nshow\n route. Indexing returns a JSON list of all users and showing returns a JSON representation of a single user.\n\n\nWe \ncould\n register the controller like so:\n\n\nlet\n \nusers\n \n=\n \nUserController\n()\n\n\ndrop\n.\nget\n(\nusers\n,\n \nhandler\n:\n \nusers\n.\nindex\n)\n\n\ndrop\n.\nget\n(\nusers\n,\n \nUser\n.\nself\n,\n \nhandler\n:\n \nusers\n.\nshow\n)\n\n\n\n\n\n\nBut \nResourceRepresentable\n makes this standard RESTful structure easy.\n\n\nextension\n \nUserController\n:\n \nResourceRepresentable\n \n{\n\n \nfunc\n \nmakeResource\n()\n \n-\n \nResource\nUser\n \n{\n\n \nreturn\n \nResource\n(\n\n \nindex\n:\n \nindex\n,\n\n \nshow\n:\n \nshow\n\n \n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nConforming \nUserController\n to \nResourceRepresentable\n requires that the signatures of \nthe \nindex\n and \nshow\n methods match what the \nResource\nUser\n is expecting.\n\n\nNow that \nUserController\n conforms to \nResourceRepresentable\n, registering the routes is easy.\n\n\nlet\n \nusers\n \n=\n \nUserController\n()\n\n\ndrop\n.\nresource\n(\nusers\n,\n \nusers\n)\n\n\n\n\n\n\ndrop.resource\n will take care of registering only the routes that have been supplied by the call to \nmakeResource()\n. In this case, only the \nindex\n and \nshow\n routes will be supplied.\n\n\n\n\nNote\n\n\ndrop.resource\n also adds useful defaults for OPTIONS requests. These can be overriden. \n\n\n\n\nActions\n\n\nBelow is a table describing all of the actions available.\n\n\n\n\n\n\n\n\nAction\n\n\nMethod\n\n\nPath\n\n\nNote\n\n\n\n\n\n\n\n\n\n\nindex\n\n\nGET\n\n\n/users\n\n\nReturns all users, optionally filtered by the request data.\n\n\n\n\n\n\nstore\n\n\nPOST\n\n\n/users\n\n\nCreates a new user from the request data.\n\n\n\n\n\n\nshow\n\n\nGET\n\n\n/users/:id\n\n\nReturns the user with the ID supplied in the path.\n\n\n\n\n\n\nreplace\n\n\nPUT\n\n\n/users/:id\n\n\nUpdates the specified user, setting any fields not present in the request data to \nnil\n.\n\n\n\n\n\n\nupdate\n\n\nPATCH\n\n\n/users/:id\n\n\nUpdates the specified user, only modifying fields present in the request data.\n\n\n\n\n\n\ndelete\n\n\nDELETE\n\n\n/users/:id\n\n\nDeletes the specified user.\n\n\n\n\n\n\nclear\n\n\nDELETE\n\n\n/users\n\n\nDeletes all users, optionally filtered by the request data.\n\n\n\n\n\n\ncreate\n\n\nGET\n\n\n/users/create\n\n\nDisplays a form for creating a new user.\n\n\n\n\n\n\nedit\n\n\nGET\n\n\n/users/:id/edit\n\n\nDisplays a form for editing the specified user.\n\n\n\n\n\n\n\n\n\n\nTip\n\n\nThe difference between \nreplace\n and \nupdate\n is subtle but important:\nIf a field does not exist in the request data (for example, the user's age is missing),\n\nupdate\n should simply not update that field where as \nreplace\n should set it to \nnil\n.\nIf required data is missing from a \nreplace\n request, an error should be thrown.\n\n\n\n\nFolder\n\n\nControllers can go anywhere in your application, but they are most often stored in the \nApp/Controllers/\n directory. \n\n\n\n\nTip\n\n\nIf you are building a large application, you may want to create your controllers in a separate module. This will allow you to perform unit tests on your controllers.", "title": "Controllers" }, { @@ -522,9 +522,14 @@ }, { "location": "/vapor/controllers/#resources", - "text": "Controllers that conform to ResourceRepresentable can be easily registered into a router as a RESTful resource. Let's look at an example of a UserController . final class UserController { \n func index ( _ req : Request ) throws - ResponseRepresentable { \n return try User . all (). makeJSON () \n } \n\n func show ( _ req : Request ) - ResponseRepresentable { \n let user = try req . parameters . next ( User . self ) \n return user \n } } Here is a typical user controller with an index and show route. Indexing returns a JSON list of all users and showing returns a JSON representation of a single user. We could register the controller like so: let users = UserController () drop . get ( users , handler : users . index ) drop . get ( users , User . self , handler : users . show ) But ResourceRepresentable makes this standard RESTful structure easy. extension UserController : ResourceRepresentable { \n func makeResource () - Resource User { \n return Resource ( \n index : index , \n show : show \n ) \n } } Conforming UserController to ResourceRepresentable requires that the signatures of the index and show methods match what the Resource User is expecting. Here is a peek into the Resource class. final class Resource Model : StringInitializable { \n typealias Multiple = ( Request ) throws - ResponseRepresentable \n typealias Item = ( Request , Model ) throws - ResponseRepresentable \n\n var index : Multiple ? \n var store : Multiple ? \n var show : Item ? \n var replace : Item ? \n var modify : Item ? \n var destroy : Item ? \n var clear : Multiple ? \n var aboutItem : Item ? \n var aboutMultiple : Multiple ? \n\n ... } Now that UserController conforms to ResourceRepresentable , registering the routes is easy. let users = UserController () drop . resource ( users , users ) drop.resource will take care of registering only the routes that have been supplied by the call to makeResource() . In this case, only the index and show routes will be supplied. Note drop.resource also adds useful defaults for OPTIONS requests. These can be overriden.", + "text": "Controllers that conform to ResourceRepresentable can be easily registered into a router as a RESTful resource. Let's look at an example of a UserController . final class UserController { \n func index ( _ req : Request ) throws - ResponseRepresentable { \n return try User . all (). makeJSON () \n } \n\n func show ( _ req : Request ) - ResponseRepresentable { \n let user = try req . parameters . next ( User . self ) \n return user \n } } Here is a typical user controller with an index and show route. Indexing returns a JSON list of all users and showing returns a JSON representation of a single user. We could register the controller like so: let users = UserController () drop . get ( users , handler : users . index ) drop . get ( users , User . self , handler : users . show ) But ResourceRepresentable makes this standard RESTful structure easy. extension UserController : ResourceRepresentable { \n func makeResource () - Resource User { \n return Resource ( \n index : index , \n show : show \n ) \n } } Conforming UserController to ResourceRepresentable requires that the signatures of \nthe index and show methods match what the Resource User is expecting. Now that UserController conforms to ResourceRepresentable , registering the routes is easy. let users = UserController () drop . resource ( users , users ) drop.resource will take care of registering only the routes that have been supplied by the call to makeResource() . In this case, only the index and show routes will be supplied. Note drop.resource also adds useful defaults for OPTIONS requests. These can be overriden.", "title": "Resources" }, + { + "location": "/vapor/controllers/#actions", + "text": "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:\nIf 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 .\nIf required data is missing from a replace request, an error should be thrown.", + "title": "Actions" + }, { "location": "/vapor/controllers/#folder", "text": "Controllers can go anywhere in your application, but they are most often stored in the App/Controllers/ directory. Tip If you are building a large application, you may want to create your controllers in a separate module. This will allow you to perform unit tests on your controllers.", @@ -782,7 +787,7 @@ }, { "location": "/json/overview/", - "text": "JSON\n\n\nJSON is an integral part of Vapor. It powers Vapor's \nConfig\n and is easy to use in both requests and responses.\n\n\nRequest\n\n\nJSON is automatically available in \nrequest.data\n alongside Form URL Encoded, Form Data, and Query data. This allows you to focus on making a great API, not worrying about what content types data will be sent in.\n\n\ndrop\n.\nget\n(\nhello\n)\n \n{\n \nrequest\n \nin\n\n \nguard\n \nlet\n \nname\n \n=\n \nrequest\n.\ndata\n[\nname\n]?.\nstring\n \nelse\n \n{\n\n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n \nreturn\n \nHello, \n\\(\nname\n)\n!\n\n\n}\n\n\n\n\n\n\nThis will return a greeting for any HTTP method or content type that the \nname\n is sent as, including JSON.\n\n\nJSON Only\n\n\nTo specifically target JSON, use the \nrequest.json\n property.\n\n\ndrop\n.\npost\n(\njson\n)\n \n{\n \nrequest\n \nin\n\n \nguard\n \nlet\n \nname\n \n=\n \nrequest\n.\njson\n?[\nname\n]?.\nstring\n \nelse\n \n{\n\n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n\n \nreturn\n \nHello, \n\\(\nname\n)\n!\n\n\n}\n\n\n\n\n\n\nThe above snippet will only work if the request is sent with JSON data.\n\n\nResponse\n\n\nTo respond with JSON, simply create a \nJSON\n object and add values to it.\n\n\ndrop\n.\nget\n(\nversion\n)\n \n{\n \nrequest\n \nin\n\n \nvar\n \njson\n \n=\n \nJSON\n()\n\n \ntry\n \njson\n.\nset\n(\nversion\n,\n \n1.0\n)\n\n \nreturn\n \njson\n\n\n}\n\n\n\n\n\n\nConvertible\n\n\nMaking your classes and structs JSON convertible is a great way to interact with APIs in an organized and DRY way.\n\n\nRepresentable\n\n\nWhen something conforms to \nJSONRepresentable\n, it can be converted into JSON.\n\n\nextension\n \nUser\n:\n \nJSONRepresentable\n \n{\n\n \nfunc\n \nmakeJSON\n()\n \nthrows\n \n-\n \nJSON\n \n{\n\n \nvar\n \njson\n \n=\n \nJSON\n()\n\n \ntry\n \njson\n.\nset\n(\nid\n,\n \nid\n)\n\n \ntry\n \njson\n.\nset\n(\nname\n,\n \nname\n)\n\n \ntry\n \njson\n.\nset\n(\nage\n,\n \nage\n)\n\n \nreturn\n \njson\n\n \n}\n\n\n}\n\n\n\n\n\n\nNow you can simply return \nuser.makeJSON()\n in your routes.\n\n\ndrop\n.\nget\n(\nusers\n,\n \nUser\n.\ninit\n)\n \n{\n \nreq\n,\n \nuser\n \nin\n\n \nreturn\n \ntry\n \nuser\n.\nmakeJSON\n()\n\n\n}\n\n\n\n\n\n\nYou can even go a step further and conform your model to \nResponseRepresentable\n. Since it's already \nJSONRepresentable\n\nyou will get the conformance for free.\n\n\nextension\n \nUser\n:\n \nResponseRepresentable\n \n{\n \n}\n\n\n\n\n\n\nNow you can return the model by itself. It will automatically call \n.makeJSON()\n.\n\n\ndrop\n.\nget\n(\nusers\n,\n \nUser\n.\ninit\n)\n \n{\n \nreq\n,\n \nuser\n \nin\n\n \nreturn\n \ntry\n \nuser\n\n\n}\n\n\n\n\n\n\nInitializable\n\n\nWhen something conforms to \nJSONInitializable\n, it can be created from JSON.\n\n\nextension\n \nUser\n:\n \nJSONInitializable\n \n{\n\n \nconvenience\n \ninit\n(\njson\n:\n \nJSON\n)\n \nthrows\n \n{\n\n \ntry\n \nself\n.\ninit\n(\n\n \nname\n:\n \njson\n.\nget\n(\nname\n),\n\n \nage\n:\n \njson\n.\nget\n(\nage\n)\n\n \n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nNow you can simply call \nUser(json: ...)\n to create a user from JSON.\n\n\ndrop\n.\npost\n(\nusers\n)\n \n{\n \nreq\n \nin\n\n \nguard\n \nlet\n \njson\n \n=\n \nreq\n.\njson\n \nelse\n \n{\n\n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n\n \nlet\n \nuser\n \n=\n \ntry\n \nUser\n(\njson\n:\n \njson\n)\n\n \ntry\n \nuser\n.\nsave\n()\n\n \nreturn\n \nuser\n\n\n}", + "text": "JSON\n\n\nJSON is an integral part of Vapor. It powers Vapor's \nConfig\n and is easy to use in both requests and responses.\n\n\nRequest\n\n\nJSON is automatically available in \nrequest.data\n alongside Form URL Encoded, Form Data, and Query data. This allows you to focus on making a great API, not worrying about what content types data will be sent in.\n\n\ndrop\n.\nget\n(\nhello\n)\n \n{\n \nrequest\n \nin\n\n \nguard\n \nlet\n \nname\n \n=\n \nrequest\n.\ndata\n[\nname\n]?.\nstring\n \nelse\n \n{\n\n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n \nreturn\n \nHello, \n\\(\nname\n)\n!\n\n\n}\n\n\n\n\n\n\nThis will return a greeting for any HTTP method or content type that the \nname\n is sent as, including JSON.\n\n\nJSON Only\n\n\nTo specifically target JSON, use the \nrequest.json\n property.\n\n\ndrop\n.\npost\n(\njson\n)\n \n{\n \nrequest\n \nin\n\n \nguard\n \nlet\n \nname\n \n=\n \nrequest\n.\njson\n?[\nname\n]?.\nstring\n \nelse\n \n{\n\n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n\n \nreturn\n \nHello, \n\\(\nname\n)\n!\n\n\n}\n\n\n\n\n\n\nThe above snippet will only work if the request is sent with JSON data.\n\n\nResponse\n\n\nTo respond with JSON, simply create a \nJSON\n object and add values to it.\n\n\ndrop\n.\nget\n(\nversion\n)\n \n{\n \nrequest\n \nin\n\n \nvar\n \njson\n \n=\n \nJSON\n()\n\n \ntry\n \njson\n.\nset\n(\nversion\n,\n \n1.0\n)\n\n \nreturn\n \njson\n\n\n}\n\n\n\n\n\n\nConvertible\n\n\nMaking your classes and structs JSON convertible is a great way to interact with APIs in an organized and DRY way.\n\n\nRepresentable\n\n\nWhen something conforms to \nJSONRepresentable\n, it can be converted into JSON.\n\n\nextension\n \nUser\n:\n \nJSONRepresentable\n \n{\n\n \nfunc\n \nmakeJSON\n()\n \nthrows\n \n-\n \nJSON\n \n{\n\n \nvar\n \njson\n \n=\n \nJSON\n()\n\n \ntry\n \njson\n.\nset\n(\nid\n,\n \nid\n)\n\n \ntry\n \njson\n.\nset\n(\nname\n,\n \nname\n)\n\n \ntry\n \njson\n.\nset\n(\nage\n,\n \nage\n)\n\n \nreturn\n \njson\n\n \n}\n\n\n}\n\n\n\n\n\n\nNow you can simply return \nuser.makeJSON()\n in your routes.\n\n\ndrop\n.\nget\n(\nusers\n,\n \nUser\n.\nparameter\n)\n \n{\n \nreq\n \nin\n\n \nlet\n \nuser\n \n=\n \ntry\n \nreq\n.\nparameters\n.\nnext\n(\nUser\n.\nself\n)\n\n \nreturn\n \ntry\n \nuser\n.\nmakeJSON\n()\n\n\n}\n\n\n\n\n\n\nYou can even go a step further and conform your model to \nResponseRepresentable\n. Since it's already \nJSONRepresentable\n\nyou will get the conformance for free.\n\n\nextension\n \nUser\n:\n \nResponseRepresentable\n \n{\n \n}\n\n\n\n\n\n\nNow you can return the model by itself. It will automatically call \n.makeJSON()\n.\n\n\ndrop\n.\nget\n(\nusers\n,\n \nUser\n.\nparameter\n)\n \n{\n \nreq\n \nin\n\n \nlet\n \nuser\n \n=\n \ntry\n \nreq\n.\nparameters\n.\nnext\n(\nUser\n.\nself\n)\n\n \nreturn\n \ntry\n \nuser\n\n\n}\n\n\n\n\n\n\nInitializable\n\n\nWhen something conforms to \nJSONInitializable\n, it can be created from JSON.\n\n\nextension\n \nUser\n:\n \nJSONInitializable\n \n{\n\n \nconvenience\n \ninit\n(\njson\n:\n \nJSON\n)\n \nthrows\n \n{\n\n \ntry\n \nself\n.\ninit\n(\n\n \nname\n:\n \njson\n.\nget\n(\nname\n),\n\n \nage\n:\n \njson\n.\nget\n(\nage\n)\n\n \n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nNow you can simply call \nUser(json: ...)\n to create a user from JSON.\n\n\ndrop\n.\npost\n(\nusers\n)\n \n{\n \nreq\n \nin\n\n \nguard\n \nlet\n \njson\n \n=\n \nreq\n.\njson\n \nelse\n \n{\n\n \nthrow\n \nAbort\n(.\nbadRequest\n)\n\n \n}\n\n\n \nlet\n \nuser\n \n=\n \ntry\n \nUser\n(\njson\n:\n \njson\n)\n\n \ntry\n \nuser\n.\nsave\n()\n\n \nreturn\n \nuser\n\n\n}", "title": "Overview" }, { @@ -812,7 +817,7 @@ }, { "location": "/json/overview/#representable", - "text": "When something conforms to JSONRepresentable , it can be converted into JSON. extension User : JSONRepresentable { \n func makeJSON () throws - JSON { \n var json = JSON () \n try json . set ( id , id ) \n try json . set ( name , name ) \n try json . set ( age , age ) \n return json \n } } Now you can simply return user.makeJSON() in your routes. drop . get ( users , User . init ) { req , user in \n return try user . makeJSON () } You can even go a step further and conform your model to ResponseRepresentable . Since it's already JSONRepresentable \nyou will get the conformance for free. extension User : ResponseRepresentable { } Now you can return the model by itself. It will automatically call .makeJSON() . drop . get ( users , User . init ) { req , user in \n return try user }", + "text": "When something conforms to JSONRepresentable , it can be converted into JSON. extension User : JSONRepresentable { \n func makeJSON () throws - JSON { \n var json = JSON () \n try json . set ( id , id ) \n try json . set ( name , name ) \n try json . set ( age , age ) \n return json \n } } Now you can simply return user.makeJSON() in your routes. drop . get ( users , User . parameter ) { req in \n let user = try req . parameters . next ( User . self ) \n return try user . makeJSON () } You can even go a step further and conform your model to ResponseRepresentable . Since it's already JSONRepresentable \nyou will get the conformance for free. extension User : ResponseRepresentable { } Now you can return the model by itself. It will automatically call .makeJSON() . drop . get ( users , User . parameter ) { req in \n let user = try req . parameters . next ( User . self ) \n return try user }", "title": "Representable" }, { diff --git a/build/2.0/sitemap.xml b/build/2.0/sitemap.xml index 9a40dee8..07dff365 100644 --- a/build/2.0/sitemap.xml +++ b/build/2.0/sitemap.xml @@ -4,7 +4,7 @@ / - 2017-06-19 + 2017-06-20 daily @@ -13,37 +13,37 @@ /getting-started/install-on-macos/ - 2017-06-19 + 2017-06-20 daily /getting-started/install-on-ubuntu/ - 2017-06-19 + 2017-06-20 daily /getting-started/toolbox/ - 2017-06-19 + 2017-06-20 daily /getting-started/hello-world/ - 2017-06-19 + 2017-06-20 daily /getting-started/manual/ - 2017-06-19 + 2017-06-20 daily /getting-started/xcode/ - 2017-06-19 + 2017-06-20 daily @@ -53,49 +53,49 @@ /vapor/folder-structure/ - 2017-06-19 + 2017-06-20 daily /vapor/droplet/ - 2017-06-19 + 2017-06-20 daily /vapor/views/ - 2017-06-19 + 2017-06-20 daily /vapor/controllers/ - 2017-06-19 + 2017-06-20 daily /vapor/provider/ - 2017-06-19 + 2017-06-20 daily /vapor/hash/ - 2017-06-19 + 2017-06-20 daily /vapor/log/ - 2017-06-19 + 2017-06-20 daily /vapor/commands/ - 2017-06-19 + 2017-06-20 daily @@ -105,7 +105,7 @@ /configs/config/ - 2017-06-19 + 2017-06-20 daily @@ -115,13 +115,13 @@ /json/package/ - 2017-06-19 + 2017-06-20 daily /json/overview/ - 2017-06-19 + 2017-06-20 daily @@ -131,31 +131,31 @@ /routing/package/ - 2017-06-19 + 2017-06-20 daily /routing/overview/ - 2017-06-19 + 2017-06-20 daily /routing/parameters/ - 2017-06-19 + 2017-06-20 daily /routing/group/ - 2017-06-19 + 2017-06-20 daily /routing/collection/ - 2017-06-19 + 2017-06-20 daily @@ -165,37 +165,37 @@ /fluent/package/ - 2017-06-19 + 2017-06-20 daily /fluent/getting-started/ - 2017-06-19 + 2017-06-20 daily /fluent/model/ - 2017-06-19 + 2017-06-20 daily /fluent/database/ - 2017-06-19 + 2017-06-20 daily /fluent/query/ - 2017-06-19 + 2017-06-20 daily /fluent/relations/ - 2017-06-19 + 2017-06-20 daily @@ -205,13 +205,13 @@ /cache/package/ - 2017-06-19 + 2017-06-20 daily /cache/overview/ - 2017-06-19 + 2017-06-20 daily @@ -221,19 +221,19 @@ /mysql/package/ - 2017-06-19 + 2017-06-20 daily /mysql/provider/ - 2017-06-19 + 2017-06-20 daily /mysql/driver/ - 2017-06-19 + 2017-06-20 daily @@ -243,13 +243,13 @@ /redis/package/ - 2017-06-19 + 2017-06-20 daily /redis/provider/ - 2017-06-19 + 2017-06-20 daily @@ -259,37 +259,37 @@ /auth/package/ - 2017-06-19 + 2017-06-20 daily /auth/provider/ - 2017-06-19 + 2017-06-20 daily /auth/getting-started/ - 2017-06-19 + 2017-06-20 daily /auth/helper/ - 2017-06-19 + 2017-06-20 daily /auth/password/ - 2017-06-19 + 2017-06-20 daily /auth/persist/ - 2017-06-19 + 2017-06-20 daily @@ -299,13 +299,13 @@ /sessions/package/ - 2017-06-19 + 2017-06-20 daily /sessions/sessions/ - 2017-06-19 + 2017-06-20 daily @@ -315,61 +315,61 @@ /http/package/ - 2017-06-19 + 2017-06-20 daily /http/request/ - 2017-06-19 + 2017-06-20 daily /http/response/ - 2017-06-19 + 2017-06-20 daily /http/middleware/ - 2017-06-19 + 2017-06-20 daily /http/body/ - 2017-06-19 + 2017-06-20 daily /http/response-representable/ - 2017-06-19 + 2017-06-20 daily /http/responder/ - 2017-06-19 + 2017-06-20 daily /http/client/ - 2017-06-19 + 2017-06-20 daily /http/server/ - 2017-06-19 + 2017-06-20 daily /http/cors/ - 2017-06-19 + 2017-06-20 daily @@ -379,19 +379,19 @@ /leaf/package/ - 2017-06-19 + 2017-06-20 daily /leaf/provider/ - 2017-06-19 + 2017-06-20 daily /leaf/leaf/ - 2017-06-19 + 2017-06-20 daily @@ -401,13 +401,13 @@ /validation/package/ - 2017-06-19 + 2017-06-20 daily /validation/overview/ - 2017-06-19 + 2017-06-20 daily @@ -417,13 +417,13 @@ /node/package/ - 2017-06-19 + 2017-06-20 daily /node/getting-started/ - 2017-06-19 + 2017-06-20 daily @@ -433,13 +433,13 @@ /core/package/ - 2017-06-19 + 2017-06-20 daily /core/overview/ - 2017-06-19 + 2017-06-20 daily @@ -449,13 +449,13 @@ /bits/package/ - 2017-06-19 + 2017-06-20 daily /bits/overview/ - 2017-06-19 + 2017-06-20 daily @@ -465,13 +465,13 @@ /debugging/package/ - 2017-06-19 + 2017-06-20 daily /debugging/overview/ - 2017-06-19 + 2017-06-20 daily @@ -481,13 +481,13 @@ /deploy/nginx/ - 2017-06-19 + 2017-06-20 daily /deploy/supervisor/ - 2017-06-19 + 2017-06-20 daily @@ -497,19 +497,19 @@ /version/1_5/ - 2017-06-19 + 2017-06-20 daily /version/2_0/ - 2017-06-19 + 2017-06-20 daily /version/support/ - 2017-06-19 + 2017-06-20 daily diff --git a/build/2.0/vapor/controllers/index.html b/build/2.0/vapor/controllers/index.html index 5a227524..46cad262 100644 --- a/build/2.0/vapor/controllers/index.html +++ b/build/2.0/vapor/controllers/index.html @@ -407,6 +407,19 @@ Resources + +
  • @@ -1644,6 +1657,19 @@ Resources + +
  • @@ -1758,27 +1784,8 @@
  • -

    Conforming UserController to ResourceRepresentable requires that the signatures of the index and show methods match what the Resource<User> is expecting.

    -

    Here is a peek into the Resource class.

    -
    final class Resource<Model: StringInitializable> {
    -    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?
    -
    -    ...
    -}
    -
    - - +

    Conforming UserController to ResourceRepresentable requires that the signatures of +the index and show methods match what the Resource<User> is expecting.

    Now that UserController conforms to ResourceRepresentable, registering the routes is easy.

    let users = UserController()
     drop.resource("users", users)
    @@ -1790,6 +1797,81 @@
     

    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.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ActionMethodPathNote
    indexGET/usersReturns all users, optionally filtered by the request data.
    storePOST/usersCreates a new user from the request data.
    showGET/users/:idReturns the user with the ID supplied in the path.
    replacePUT/users/:idUpdates the specified user, setting any fields not present in the request data to nil.
    updatePATCH/users/:idUpdates the specified user, only modifying fields present in the request data.
    deleteDELETE/users/:idDeletes the specified user.
    clearDELETE/usersDeletes all users, optionally filtered by the request data.
    createGET/users/createDisplays a form for creating a new user.
    editGET/users/:id/editDisplays 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.