Week 6
The Vapor team was very very busy steamrolling ahead with the NIO implementation this week, so no new features, but loads and loads of bugfixes are set to be merged in along with the NIO branches, potentially later this week. If you’re getting antsy to see what’s been happening though, check out the NIO branches of your favorite packages.
Community Contributions
GROUP BY
Added To Database Kit
@rafiki270 implemented the ability to use the SQL GROUP BY
clause. GROUP BY
allows the use of advanced aggregate functions in SQL queries. A simple example would be “I want to know how many users signed up each day for the last month.” The query for this might be written this way:
SELECT
DATE(signup_date) AS date, COUNT(userId)
FROM Users
WHERE
signup_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
GROUP BY signup_date
Now Fluent can produce a similar result, though there’s no higher-level API for using it yet. Stay tuned!
Peek
@pedantix added the ability to peek at data in byte buffers, improved error handling, and added a few other enhancements.
Fixed Grouping Bug Replacing AND
with OR
@MrMage fixed a bug where AND
conditions in database queries would be serialized as OR
conditions instead!
https://github.com/vapor/fluent/pull/399
Fixed Typo That Made The Short Flag For --verbose
= -c
@siemensikkema fixed it!
Schema Generation
@SandorDobi added a check for the PostgreSQL server version so Fluent will not attempt to generate IDENTITY COLUMN
s if the server doesn’t support them.
Tutorials
How to use Leaf
Martin Lasek is going through and updating all of his Vapor 2 tutorials for Vapor 3, so we should be seeing a lot from him for a few weeks to come! In this tutorial you’ll learn how to use Leaf, Vapor’s templating language, to create a web page and populate it with data from your server.
https://medium.com/@martinlasek/tutorial-how-to-use-leaf-70d796831ec5
Diving into Vapor, Part 1: Up and Running with Vapor 3
In this tutorial we will cover setting up an environment for building web apps with Swift, creating a Vapor project, examining the structure of a project, and creating a simple route. If you’re just now getting started with Vapor, this is a great place to begin.
https://theswiftwebdeveloper.com/diving-into-vapor-part-1-up-and-running-with-vapor-3-edab3c79aab9
Talks
NIO Announcement and Introduction At try! Swift Tokyo
If you want to know more about NIO, the new asynchronous underpinnings of Vapor, check out this talk by Norman Maurer of Apple and NETTY fame! Norman goes over a comparison of async methodologies, the motivation behind NIO, and then a rundown of how it works and how he thinks it will be applied.
https://www.youtube.com/watch?v=QJ3WG9kRLMo
Microtutorial
This week we’ll be talking about how to set up your own services by creating a service you can use to send emails from your Vapor apps. You can find the repo for VaporMailgunService
here.
If you’ve used Leaf
or EngineClient
before, you’ve already used a Service!
// config
try services.register(LeafProvider())
// router
let leaf = try req.make(LeafRenderer.self)
First we set up the protocol that our service will be registered to.
public protocol MailgunProvider: Service {
var apiKey: String { get }
var customURL: String { get }
var numMailSent: Int { get set }
mutating func sendMail(data content: MailgunFormData, on req: Request) throws -> Future<Response>
}
Then we conform to our protocol and implement our service. In this case, we’ll be sending an email.
// Singleton
public class MailgunEngine: MailgunProvider {
public var apiKey: String
public var customURL: String
public var numMailSent: Int = 0
public init(apiKey: String, customURL: String) {
self.apiKey = apiKey
self.customURL = customURL
}
public func sendMail(data content: MailgunFormData, on req: Request) throws -> Future<Response> {
// Send an email using the config from content
numMailSent += 1
}
}
// Non-singleton
public struct MailgunStructEngine: Mailgun {
public var apiKey: String
public var customURL: String
public var numMailSent: Int = 0
public init(apiKey: String, customURL: String) {
self.apiKey = apiKey
self.customURL = customURL
}
public mutating func sendMail(data content: MailgunFormData, on req: Request) throws -> Future<Response> {
// Send an email using the config from content
numMailSent += 1
}
}
Then we can configure our service for use.
// configure.swift
let mailgunEngine = MailgunEngine(apiKey: "<mailgun key>", customURL: "mg.example.com")
services.register(mailgunEngine, as: Mailgun.self)
And finally use our service to send some email!
// routes.swift
var mailgunClient = try req.make(Mailgun.self)
print(mailgunClient.numMailSent)
return try mailgunClient.sendMail(data: content, on: req)
Using the singleton version and sending mail three times will print
0
1
2
but using the non singleton version will print
0
0
0
because a new version is created with each request. In most cases, you’ll want to create Service
structs for your own use, because Service
singletons are not guaranteed to be thread safe. To read more about Service
s, check out the newly updated section of the docs.
https://github.com/twof/VaporMailgunService https://docs.vapor.codes/3.0/getting-started/services/