MantleFramework/Mantle — pull request #272 by bartvandendriessche (2014-03-17 12:33:25+00:00)
Title: Check if model is a placeholder before overriding existing CoreData properties

This is a quick hack I applied to work around the issue raised in #260.

I'll try to explain the context a bit.

Given a REST api with the following endpoints:

`GET /categories` returning a list of categories. e.g.:

```json
{
results: [
{
"id": 1,
"name": "2013 catalog",
"description": "old 'n busted",
},
{
"id": 2,
"name": "2014 catalog",
"description": "new hotness",
}]
}
```

`GET /items` returning a list of items, where items belong to a category e.g.:

```json
{
results: [
{
"id": 1,
"name": "iPhone 5S",
"category_id": 1
},
{
"id": 2,
"name": "iPhone 6",
"category_id": 2
}]
}
```

I'm using CoreData, and in my DataModel, there's a relationship between `Item` and `Category`.

For `Category` the mapping from json to CoreData is pretty straightforward.

For `Item`, I have a special `NSValueTransformer` that transforms the category_id `2` into `{ "id": 2 }`. This will create an empty (placeholder) `Category` entry in the CoreData store.

Now, imagine the following sequence of events:

`GET /categories` will create CoreData entries for every `Category`
`GET /items` will create CoreData entries for every `Item`, but it will also nil out all existing properties (except `id`) for `Category`s that are referenced in the `GET /items` payload.

What my patch does is, it checks to see if a given instance is a "placeholder" (in the example above, a `Category` for which only the `id` property has a value), and if it encounters one, it wil only insert it into the CoreData store if it is missing. If an existing object can be found for the given `id`, that object is returned without having it's properties overwritten with nil values.

The same kind of functionality would be useful to identify `tombstone` objects, or objects that need to be deleted based on the value of certain properties.

In our existing example, we could add a `deleted_at` property to `Item`. Then when converting `Item` instances into `NSManagedObjects` we could check for the `deleted_at` property, and if it's non-nil, it indicates that this particular `Item` should never be inserted, and any existing `Item` with the same `id` should be deleted from the CoreData store.

Of course, the criteria used to determine when something is a placeholder, or when something is a tombstone should be extensible, sort of like how `+propertyKeysForManagedObjectUniquing` handles uniquing.