Spine icon indicating copy to clipboard operation
Spine copied to clipboard

Fetching relationships objects

Open markst opened this issue 8 years ago • 6 comments

Let's say I have an object Timesheet which has a relationship Entries of 100 objects.

Our API expects a URI as: /timesheets/1234/entries

Is there a way for Spine to generate the appropriate URL without concating a URL as so:

var query = Query(resourceType: Entry.self, path: "/timesheets/\(timesheet.id!)/entries")

markst avatar Oct 27 '16 07:10 markst

It seems that there are alternatives such as:

var query = Query(resourceType: Entry.self)
query.whereProperty("timesheet-id", equalTo: self.timesheet.id)

or

var query = Query(resourceType: Timesheet.self)
query.include("entries") // Sideload relationships

Which both produce URL's which can't be paginated.

markst avatar Oct 27 '16 07:10 markst

SaveOperation can update the relationships using the Resource linkage data. However it would be good for this to be possible for fetching linkage data too.

Or perhaps being able to get that URL as: router.urlForRelationship(timesheet.relationships["entries"], ofResource: timesheet)

...

markst avatar Oct 27 '16 07:10 markst

Does Query(resourceType: Entry.self, resourceCollection: self.timesheet.entries) work for you? The query is then initialised with the related link from the JSON:API response. This should point to the entries of that timesheet as long as your back-end includes it in the timesheet response.

PS: router.urlForRelationship returns the self URL of the relationship, which is not what you need.

wvteijlingen avatar Oct 27 '16 10:10 wvteijlingen

Thanks @wvteijlingen. This has worked for instances when the relationship includes the appropriate links.

However there are instances when we have the ids and type of a relationship defined & we'd like to resolve a resources relationship.

 },
 "relationships":{  
    "skills":{  
       "data":[  
          {  
             "id":"59451a73-1e14-464d-a4a0-7136ec2bf644",
             "type":"skills"
          },
          {  
             "id":"4c43fb46-a5d1-471a-ad87-a4289bccc939",
             "type":"skills"
          },
          {  
             "id":"a7e91fb3-8113-434b-a8e4-4d1f1e169992",
             "type":"skills"
          },

If I expose the ResourceIdentifier type & id I can generate of required ids & fetch:

var skillIds: [String]
skillIds = selectedJobCategories.reduce([], { (results, jobCategory) -> [String] in
    var results = results

    results.append(contentsOf: jobCategory.skills!.linkage!.reduce([], { (results, resourceIdentifier) -> [String] in
        var results = results
        results.append(resourceIdentifier.id)
        return results
    }))
    
    return results
})
SpineSingleton.find(skillIds, ofType: Skill.self).onSuccess { [weak self] in

It would be sweet if this were available as a query & resolve the relationships on the fetching resource...?

markst avatar Feb 21 '17 03:02 markst

This is infact a better alternative for us:

var query = Query(resourceType: Skill.self)
selectedJobCategories.forEach { (jobCategory) in
    query.whereRelationship("jobCategory", isOrContains: jobCategory)
}
SpineSingleton.find(query).onSuccess { [weak self] in

markst avatar Feb 21 '17 03:02 markst

I hit a similar issue this morning, but to solve my case I just need access to the ResourceIdentifier struct's id property. Does anyone know why that is made to be private?

ryancarlson avatar Apr 21 '17 15:04 ryancarlson