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

Append to Spine URL for resources #149

Open cmwall opened 7 years ago

cmwall commented 7 years ago

I would like to be able to fetch resources like so (default way):

/resources

but, I would also like to be able to add a function that can fetch resources with a different path, like so:

/resources/available

I have tried to set the baseURL in a separate initializer to /resources/available, however this results in the URL for fetch calling to /resources/available/resources which is not what I want.

Is there a specific way of appending to the Spine URL for a single function?

e.g.

fetchAllResources() -> /resources fetchAllAvailableResources() -> /resources/available

cmwall commented 7 years ago

I have another question regarding error handling.

Whenever I catch an error in the error block for my save function, I am not able to get any of the details from the error.

dump(error) responds with:

Spine.SpineError.serverError
  ▿ serverError: (2 elements)
    - .0: 422
    ▿ .1: Optional([Spine.APIError(id: nil, status: nil, code: nil, title: nil, detail: Optional("Unavailable resource provided"), sourcePointer: Optional("/data/attributes/resources"), sourceParameter: nil, meta: nil)])
      ▿ some: 1 element
        ▿ Spine.APIError
          - id: nil
          - status: nil
          - code: nil
          - title: nil
          ▿ detail: Optional("Unavailable resource provided")
            - some: "Unavailable resource provided"
          ▿ sourcePointer: Optional("/data/attributes/resources")
            - some: "/data/attributes/resources"
          - sourceParameter: nil
          - meta: nil

However I would like to be able to access the error detail and the error status code to determine what to do with the resulting error.

I have tried casting the error to NSError as well as multiple SpineError types but none have given me the information I need.

My save function looks like this:

  func saveResource(resource: ResourceModel) {
    spine.registerResource(EventModel.self)
    spine.registerResource(ResourceModel.self)
    spine.registerResource(ReservationModel.self)

    spine.save(resource)
      .onSuccess { _ in
        print("Save Resource Successful")
      }
      .onFailure { error in
        print("Error: \(error)")
    }
  }

and I am calling it like this:

      resourceApiHelper.saveResource(resource: newResource,
        successBlock: { _ in
          self.performSegue(withIdentifier: "unwindToPreviousView", sender: self)
        },
        errorBlock: { error in
          dump(error)
        }
      )
wvteijlingen commented 7 years ago

I think for default endpoints you can use a custom Query. If I recall correctly, this can be both a relative or absolute URL.

let query = Query(url: URL(string: "http://example.com/resources/available"))
spine.find(query)

For the error handling the ServerError contains the HTTP status code, and an array of errors returned by your api. This assumes your API follows the JSON:API specification for error objects. You should be able to get them as follows:

switch error {
  // Handle other errors here.
  case SpineError.serverError(let statusCode, let apiErrors):
    // Do something with statusCode and apiErrors
  default: ()
}