Simpler approach to POST update(_:) method?

In chapter 9, after we’ve added a parent-child relationship from User to Acronym, we have to revisit our previous update(_:slight_smile: method to include the newly-added UserID property, like so:

func updateHandler(_ req: Request) throws -> Future<Acronym> {
  return try flatMap(to: Acronym.self,
                     req.parameter(Acronym.self),
                     req.content.decode(Acronym.self)) {
    acronym, updatedAcronym in
    
    acronym.short = updatedAcronym.short
    acronym.long = updatedAcronym.long
    acronym.userID = updatedAcronym.userID
    return acronym.save(on: req)
  }
}

I found myself instead using an approach that seemed natural to me:

func updateHandler(_ req: Request) throws -> Future<Acronym> {
  return try flatMap(to: Acronym.self, 
                     req.parameter(Acronym.self), 
                     req.content.decode(Acronym.self)) { 
  existingAcronym, updatedAcronym in

  updatedAcronym.id = existingAcronym.id
  return updatedAcronym.update(on: req)
  }
}

Given how much less repeating ourselves there is in Vapor 3, I find myself really wanting to avoid any kind of repetition, and this approach appeals to me in that I don’t have to touch my controller methods as I modify my model. But I’m wondering… Is there anything less performant or error-prone about my approach that I’m perhaps missing?

@brian_bee so your approach is relying on a feature of Fluent that could change in the future. Effectively two models with the same ID are the same - which they technically are. When you save updatedAcronym you are saving a different model to the one that exists in the database. It works because Fluent uses the ID to compare the models, which is absolutely fine! So I don’t think there should be any issues. From a performance point of view I can’t see any issues with what you have, though it may depend on whether Acronym is a class or a struct for copy semantics.

One thing you will hit in the next release is when it comes to updating a user. When we get to Authentication the user is pulled from the request instead of the Acronym - just something to be aware of. But for now, keep going with your method!

Thanks for that – all makes sense, and the larger context is very helpful.