user11042303
user11042303

Reputation:

Problem saving two models and retrieving a record from the database with Fluent

I'm just getting started with programming and vapor and have the following querying problem.

When a user makes a request to /api/trip/new to create a new trip, I want to retrieve the first driver from the database and assign their ID to a Trip object. Then I want to save both the trip and trip request in the database.

I have the following code:

func newTripHandler(_ req: Request, data: TripRequestCreateData) throws -> Future<TripRequest> {
let passenger = try req.requireAuthenticated(Passenger.self)
let tripRequest = try TripRequest(pickupLat: data.pickupLat,
                                  pickupLng: data.pickupLng,
                                  destLat: data.destLat,
                                  destLng: data.destLng,
                                  pickupAddress: data.pickupAddress,
                                  destAddress: data.destAddress,
                                  passengerId: passenger.requireID())

//Passenger's location
let lat = tripRequest.pickupLat
let lng = tripRequest.pickupLng

//Passenger's destination
let toLat = tripRequest.destLat
let toLng = tripRequest.destLng

let trip = Trip(passengerId: tripRequest.passengerId!,
                pickupLat: lat,
                pickupLng: lng,
                destLat: toLat,
                destLng: toLng,
                pickupAddress: tripRequest.pickupAddress,
                destAddress: tripRequest.destAddress)

let driver = Driver.query(on: req).first().unwrap(or: Abort(.notFound))

let driverId = driver.map(to: Driver.self) { driver in
  return driver.id
}

trip.driverId = driverId

print(trip)

return tripRequest.save(on: req)
}

struct TripRequestCreateData: Content {
  let pickupLat: Double
  let pickupLng: Double
  let destLat: Double
  let destLng: Double
  let pickupAddress: String
  let destAddress: String
}

I’m not sure how to save two models and how to properly retrieve the driver from the database. The driverId constant is of type EventLoopFuture instead of Driver so I can't assign the ID to trip's driverId property.

How can I adjust my code to achieve this?

Upvotes: 1

Views: 271

Answers (1)

code28
code28

Reputation: 181

When working with the database, you only get Futures. (More about Futures in The Vapor Docs.)

So to get the driver, you already used the correct code, but have to go on inside the map codeblock. When returning a Future inside the map, use flatMap, so you don't have a Futures inside Futures.

Try this:

return Driver.query(on: req).first().unwrap(or: Abort(.notFound)).flatMap { driver in
    trip.driverId = driver.id

    return trip.save(on: req).flatMap { trip in
        return tripRequest.save(on: req)
    }
}

(I chose this way to show how Futures work - there are some ways to make this code cleaner, e.g. chaining Futures or using flatten.)

Upvotes: 4

Related Questions