Restkit: GET remote linked object when foreign key refers to missing local object in Core Data - core-data

I cannot figure out if Restkit is able to download an object not present locally, in particular when a foreign key is referring to that missing object in a to-one relationship in Core Data.
Take the following example:
- contact 1 refers to company 2
contact 1 is present in the local db but company 2 is not
when in the UI the user inspects the details of contact 1, then a GET for the contact 1 is performed
the GET returns a JSON containing among other contact details the property company_id = 2
I have already setup Restkit via the foreign key convention where I store the foreign key in the contact object (companyID) and I link it to the remote identifier (identifier) stored in the company object:
[contactResponseMapping addConnectionForRelationship:#"forCustomer" connectedBy:#{#"companyID" : #"identifier"}]
I do not manage in this case to configure restkit to download the entity (referred to by the company_id) if not present in the local db.
Is this possible?
The alternative workaround would be to override the companyID setter and double check if the entity exists and if not download the entity, although this is not desirable to me as I have setup an engine that everytime that an object is edited receives a notification and post it to the server. This means I'd have to block the thread execution until the linked object is downloaded.
Also is this mechanism called lazy loading? or hydrating entities?
I cannot find any other similar cases around.
Hope you can help, going a bit crazy on this.
Thanks a lot.
PS: I am using restkit 0.21.0 (i.e. the latest development release which Blake Watters confirmed to be stable)

This is not a feature that RestKit currently offers (probably because of the types of issues you discuss).
For your workaround, consider what your engine is doing in relation to relationship edits - how are they pushed back to the server? Are they always pushed?
Also, think about creating stub objects for your 'foreign' objects so that at least some representation always exists (there are a couple of ways to do this, you can setup mappings to accomplish the task). Then when you come to use one of these objects you can hydrate / lazy load it.
See also Clarifying terminology : "Hydrating" an entity : Fetching properties from the DB.

Related

Fetching Initial Data from CloudKit

Here is a common scenario: app is installed the first time and needs some initial data. You could bundle it in the app and have it load from a plist or something, or a CSV file. Or you could go get it from a remote store.
I want to get it from CloudKit. Yes, I know that CloudKit is not to be treated as a remote database but rather a hub. I am fine with that. Frankly I think this use case is one of the only holes in that strategy.
Imagine I have an object graph I need to get that has one class at the base and then 3 or 4 related classes. I want the new user to install the app and then get the latest version of this class. If I use CloudKit, I have to load each entity with a separate fetch and assemble the whole. It's ugly and not generic. Once I do that, I will go into change tracking mode. Listening for updates and syncing my local copy.
In some ways this is similar to the challenge that you have using Services on Android: suppose I have a service for the weather forecast. When I subscribe to it, I will not get the weather until tomorrow when it creates its next new forecast. To handle the deficiency of this, the Android Services SDK allows me to make 'sticky' services where I can get the last message that service produced upon subscribing.
I am thinking of doing something similar in a generic way: making it possible to hold a snapshot of some object graph, probably in JSON, with a version token, and then for initial loads, just being able to fetch those and turn them into CoreData object graphs locally.
Question is does this strategy make sense or should I hold my nose and write pyramid of doom code with nested queries? (Don't suggest using CoreData syncing as that has been deprecated.)
Your question is a bit old, so you probably already moved on from this, but I figured I'd suggest an option.
You could create a record type called Data in the Public database in your CloudKit container. Within Data, you could have a field named structure that is a String (or a CKAsset if you wanted to attach a JSON file).
Then on every app load, you query the public database and pull down the structure string that has your classes definitions and use it how you like. Since it's in the public database, all your users would have access to it. Good luck!

MVCSiteMapProvider overriding GetDynamicNodeCollection with multiple requests

I am using MVCSiteMapProvider for MVC5. I have created my own implementation of DynamicNodeProviderBase to dynamically create nodes in my site map based on a collection of categories for our product catalogue.
I am using SimpleInjector and have a MvcSiteMapProviderContainerInitializer that I pull from the sample project for the site map provider. This is working fine.
However, when calling Html.MvcSiteMap().SiteMapPath() this results a call to GetDynamicNodeCollection for every request. Can the dynamic node collection be done once per lifetime of the container rather then on a per request basis?
Thanks in advance
The class I have implemented is actually created as a singleton, so for now I have initialised the nodes collection from within the constructor. This will do now.
However, I saw this blog post from 2012 but the interface seems to have changed in later versions of the provider so this is no longer possible
http://xharze.blogspot.co.uk/2012/04/inside-mvcsitemapprovider-part-2.html?m=1

Issue with CouchDB

In the TAMA implementation, I came across an issue with Couchdb. (Version 1.2.0) ,
We are using named documents to maintain unique constraint logic in the application. (named documents : whose _id is user defined, and not couch generated.)
We are using the REST API to add the documents to Couchdb, where we found strange behavior :
When we try to recreate the documents using HTTP PUT which have been deleted in the past(because of bug in the code), the documents are not created the first time .
HTTP Put - Returns HTTP 200, but doc is not saved in couchdb.
Again trying the same request,
HTTP Put - Returns HTTP 200 and adds the doc in database.
HTTP PUT request needs to be sent twice to create and save the doc.
I have checked that the above bug is reproducible for deleted docs, i.e the response for GET _id is {"error":"not_found","reason":"deleted"}.
This looks like a bug in CouchDB to me, could you please let us know if you could think of any scenario where above error might occur and any possible workarounds/solutions ?
Couchdb has a builtin mechanism to ensure that you do not overwrite the same document as someone else.
If you PUT any existing document, you'll have to accompany this process with the current doc._rev value, so that couchdb can confirm the document you are updating is based on the most recent version in the database.
I've not come across this case with deletions, but it makes sense to me that couchdb should not allow you to overwrite a deleted document as the assumption should be, you just don't know about the deletion.
Have you tried if you can access the revision of the deleted document and if so, whether by adding it to the new document, you can succeed with the PUT on the first call?

RestKit and Core Data - How to POST data?

I am using RestKit .22.0 with Core Data integration, both of which I'm pretty unfamiliar with. I followed the RKGist tutorial and was able to learn how to get objects from a REST endpoint, set up object mappings, add routes, and see the data from the web service correctly insert into the Core Data sqlite database.
Now I'm starting to work on persisting objects to the web service, but can't find any information on how best to do this. It seems like there are multiple ways to skin a cat with RestKit, so I wanted to see what the best practices are for POST/PUTing data.
When POSTing a new object, do you usually save the object in the managed object context first, then call [[RKObjectManager sharedManager] postObject:path:parameters:success:failure:]? Or is there some RestKit method that performs both of these operations at once?
If you first save the object in Core Data then POST it to the web service, is RestKit going to be able to update the already inserted object with the service's database identification attributes? Does the [[RKObjectManager sharedManager] postObject:path:parameters:success:failure:] method do this for you?
If there was an error POSTing the object, what is the typical way you'd retry the POST? Would you look for some sort of flag in the core data managed object and retry in a separate thread?
Thanks!
Yes, then the response from the POST updates that same object (perhaps filling in the server specified unique id)
Yes, updating the POSTed object is the default behaviour (you need to specify the response mapping and the response must be a single object)
No separate thread generally, and it depends what caused the error. Have a flag that indicates it's uploaded and retry when network connection is reestablished

Syncing Local Domain Entity Changes When Using CQRS

Lets suppose I have a basic CustomerEntity which has the following attributes
Name
Surname
IsPreferred
Taking CQRS in it's simplest form I would have the following services
CustomerCommandService
CustomerQueryService
If on the CustomerCommandService I call UpgradeToPreferred(CustomerEntity) The store behind it will update and any queries will reflect this. So far so good.
My question is how to I sync this back to the local entity I have? I have called the UpgradeToPreferred() method on the service not on the entity so it will not reflect in the local copy unless I query the CustomerQueryService and get the update which seems a tad redundant.
..Or am I doing it wrong?
EDIT:
To clarify, the question is. If I am going through a command service to modify the entity in storage and not calling the command on the entity directly or editing it's properties how should I handle the same modification on the entity I have in memory.
Few things wrong here. Your comand service takes a command, not an entity. So if you want to upgrade that customer to be preferred, then the command would be the intent (makecustomerpreferred) and the data needed to perfomr the command (a customer identification would suffice). The service would load up the entity using the identification, and invoke the makepreferred behavior on the entity. The entity would be changed internally. Persistence would map it back to the database. Ergo, no need to resync with the database.

Resources