wvteijlingen / Spine

A Swift library for working with JSON:API APIs. It supports mapping to custom model classes, fetching, advanced querying, linking and persisting.
MIT License
266 stars 109 forks source link

POST to a resource that belongs to another resource #164

Open Croge32 opened 7 years ago

Croge32 commented 7 years ago

Hello,

I was wondering how I'd go about posting to a resource that belongs to another resource?

We have endpoints for a user at v1/users and for an energy assessment at /v1/users/{id}/energy_assessment

My POST to users works fine, but I'm struggling to POST to the energy assessment.

My EnergyAssessment object:

import Foundation
import Spine

class EnergyAssessment: Resource {
  var bodyFat: NSNumber?
  var height: NSNumber?
  var weight: NSNumber?
  var user: User?

  override class var resourceType: ResourceType {
    return "energy_assessment"
  }

  override class var fields: [Field] {
    return fieldsFromDictionary([
      "bodyFat": Attribute().serializeAs("body_fat"),
      "height": Attribute(),
      "weight": Attribute(),
      "user": ToOneRelationship(User.self)
    ])
  }

  required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  required init() {
    super.init()
  }

...

And my API helper method:

func saveUserEnergyAssessment(user: User, successBlock: @escaping (_ object: EnergyAssessment) -> Void, errorBlock: @escaping (_ error: SpineError) -> Void) {
    spine?.registerResource(User.self)
    spine?.registerResource(EnergyAssessment.self)

    let token = "bearer \(Locksmith.loadDataForUserAccount(userAccount: "army-app-user")!["token"]!)"
    (spine?.networkClient as! HTTPClient).setHeader(Constants.authorizationLabel, to: token)

    spine?.save(user.energyAssessment!)
      .onSuccess { resource in
        successBlock(resource)
      }
      .onFailure { error in
        errorBlock(error)
    }
  }

And it should be noted that Spine was initialized with a baseURL that looks like https://myurl.com/v1

Any advice?

Croge32 commented 7 years ago

I was also curious if there was a way I could get the request JSON that spine serializes out for debugging purposes?

wvteijlingen commented 7 years ago

I think this is currently not possible in Spine. What you can do is POST it to /v1/energy_assessments. If you assign a user to the user property, Spine should include the id of this user in the payload under the relationships key.

You can log all the network requests by setting the log level to debug: Spine.setLogLevel(.debug, forDomain: .networking). This will include the POST body as well.

Croge32 commented 7 years ago

I found a sort of hack solution by changing the base URL for the particular request to include /user{id} and the request works for me.