OliverLetterer / SLRESTfulCoreData

Objc naming conventions, autogenerated accessors at runtime, URL substitutions and intelligent attribute mapping
MIT License
178 stars 13 forks source link

creating with nested attributes #10

Closed jpaas closed 10 years ago

jpaas commented 10 years ago

One thing I'm having trouble with is creating a new object with nested attributes. createWithCompletionHandler -> postToURL updates the parent object, but does not have any provision to deal with the children that are returned as part of the response.

As far as I can tell I have to implement my own postToURL because its the only way to get access to the JSONObject.

Am I missing something?

OliverLetterer commented 10 years ago

Can you overwrite -[NSManagedObject rawJSONDictionary] and add all children there?

jpaas commented 10 years ago

That's what I do to build the JSON that I post to the server. The issue is with the response JSON. The parent object gets updated with the JSON response, but not the children.

OliverLetterer commented 10 years ago

i guess i would need a more detailed example.

jpaas commented 10 years ago

In my example, I have an order containing order items. I post this to a rails server where my model has the directive:

accepts_nested_attributes_for :order_items

So I've created the following method on my order:

- (NSDictionary *)rawJSONDictionary {
    NSMutableArray *orderItemsDicts = [NSMutableArray arrayWithCapacity:self.orderItems.count];
    for (DRAOrderItem *orderItem in self.orderItems) {
        [orderItemsDicts addObject:orderItem.rawJSONDictionary];
    }

    NSString *paidCentsString = [[NSNumber numberWithFloat:[[self total].total floatValue]] cleanCurrencyStringFromNumber];
    int paidCents = [paidCentsString floatValue] * 100;

    NSDictionary *orderDict = [NSDictionary dictionaryWithObjectsAndKeys:
             orderItemsDicts, @"order_items_attributes"
            ,[NSNumber numberWithInteger:paidCents], @"paid_cents"
            ,self.storeLocation.id, @"store_location_id"
            ,nil
            ];

    return [NSDictionary dictionaryWithObjectsAndKeys:
             self.paymentMethod.id, @"payment_method_id"
            ,orderDict, @"order"
            ,nil];
}

Posting to the server works great. It saves the order and the order items and returns the following JSON:

{
    "id": "2c04e77dc2e01027194d20da",
    "order_items": [
        {
            "id": 35,
            "order_id": "2c04e77dc2e01027194d20da",
            "price_paid_amount": 7.99,
            "price_paid_currency": "CAD",
            "price_paid_formatted": "$7.99",
            "product_brand": "Essie",
            "product_id": 6656,
            "product_name": "Nail Polish - Miami Nice",
            "product_price_id": 6656,
            "product_source_id": "source1",
            "quantity": 1
        }
    ],
    "paid_amount": 9.03,
    "paid_currency": "CAD",
    "paid_formatted": "$9.03",
    "payment_id": "10000223",
    "payment_time": "2013-10-30T15:43:53.000Z",
    "store_location_id": 6,
}

My core data order gets updated with id, payment_id, payment_time, etc. But I need to update the order items as well.

OliverLetterer commented 10 years ago

There are multiple tests in SLRESTfulCoreDataQueryInterfaceTests which verify that too-many relations are updated properly. You can take a look there to check if your setup is configured in a wrong way or if this is an issue with SLRESTfulCoreData, you can write a test case included in a pull request and I'll be happy to fix it.

jpaas commented 10 years ago

I had a look at the tests and there is actually only 1 test for each of createWithCompletionHandler and postToURL. Neither test involves the updating of relations.

I did find the problem though. In NSManagedObject+SLRESTfulCoreDataQueryInterface.m, both postToURL and putToURL call updateWithRawJSONDictionary: on backgroundSelf. They should be calling updateWithRawJSONDictionary:relationshipUpdateLevel.

The only complication is that updateWithRawJSONDictionary:relationshipUpdateLevel is a private method.

jpaas commented 10 years ago

Aside from this issue, I have a few other places in my code where I call updateWithRawJSONDictionary:relationshipUpdateLevel. It would be nice to have it public.