diff --git a/nsrails/Source/NSRRemoteObject.m b/nsrails/Source/NSRRemoteObject.m index 9afe34e..ccc4078 100644 --- a/nsrails/Source/NSRRemoteObject.m +++ b/nsrails/Source/NSRRemoteObject.m @@ -62,7 +62,6 @@ - (id) remoteRepresentationOfObjectForProperty:(NSRProperty *)prop; + (NSString *) routeForControllerMethod:(NSString *)customRESTMethod; - (NSString *) routeForInstanceMethod:(NSString *)customRESTMethod httpVerb:(NSString *)verb; -- (void) assertCanSendInstanceRequestOnVerb:(NSString *)httpVerb; + (NSString *) NSRMap; + (NSString *) NSRUseModelName; @@ -825,17 +824,33 @@ + (NSString *) routeForControllerMethod:(NSString *)method return route; } -- (BOOL) verbUsesPrefixConstruction:(NSString *)verb +- (NSString *) routeForInstanceMethod:(NSString *)method httpMethod:(NSString *)verb { - NSArray *allowedVerbs = [self performSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefixMethods)]; - - return (!allowedVerbs || [allowedVerbs containsObject:verb] || [allowedVerbs containsObject:[verb lowercaseString]]); -} - -- (NSString *) routeForInstanceMethod:(NSString *)method httpVerb:(NSString *)verb -{ - [self assertCanSendInstanceRequestOnVerb:verb]; + if (!self.remoteID) + { + [NSException raise:NSRNullRemoteIDException format:@"Attempt to %@ to %@/:id/%@ with %@ instance that has a nil remoteID.",verb,[[self class] masterPluralName],method ? method : @"",[self class]]; + } + NSRRemoteObject *prefix = nil; + BOOL shouldUsePrefixConstruction = NO; + if ([self respondsToSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefix)]) + { + NSArray *allowedVerbs = [self performSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefixMethods)]; + + shouldUsePrefixConstruction = (!allowedVerbs || + [allowedVerbs containsObject:verb] || + [allowedVerbs containsObject:[verb lowercaseString]]); + + if (shouldUsePrefixConstruction) + { + prefix = [self performSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefix)]; + if (!prefix.remoteID) + { + [NSException raise:NSRNullRemoteIDException format:@"Attempt to %@ %@ instance with a prefix association (%@ instance) that has a nil remoteID.",verb,[self class],[prefix class]]; + } + } + } + // 1/something // posts/1/something // other/5/posts/1/something (only if prefix - use everything as instance method of prefix object) @@ -843,11 +858,8 @@ - (NSString *) routeForInstanceMethod:(NSString *)method httpVerb:(NSString *)ve NSString *route = [[self.remoteID stringValue] stringByAppendingPathComponent:method]; route = [[self class] routeForControllerMethod:route]; - NSRRemoteObject *prefix = [self performSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefix)]; - if (prefix && [self verbUsesPrefixConstruction:verb]) - { - route = [prefix routeForInstanceMethod:route httpVerb:verb]; - } + if (shouldUsePrefixConstruction) + route = [prefix routeForInstanceMethod:route httpMethod:verb]; return route; } @@ -855,32 +867,15 @@ - (NSString *) routeForInstanceMethod:(NSString *)method httpVerb:(NSString *)ve #pragma mark Performing actions on instances -- (void) assertCanSendInstanceRequestOnVerb:(NSString *)verb -{ - if (!self.remoteID) - { - [NSException raise:NSRNullRemoteIDException format:@"Attempted to update, delete, or retrieve an object with no ID. (Instance of %@)",[self class]]; - } - else if ([self respondsToSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefix)] && - [self verbUsesPrefixConstruction:verb]) - { - NSRRemoteObject *prefix = [self performSelectorWithoutClimbingHierarchy:@selector(NSRUseResourcePrefix)]; - if (!prefix.remoteID) - { - [NSException raise:NSRNullRemoteIDException format:@"Attempted to update, delete, or retrieve an object whose prefix association (%@) has no ID. (Instance of %@)",[prefix class],[self class]]; - } - } -} - - (id) remoteRequest:(NSString *)httpVerb method:(NSString *)customRESTMethod body:(id)body error:(NSError **)error { - NSString *route = [self routeForInstanceMethod:customRESTMethod httpVerb:httpVerb]; + NSString *route = [self routeForInstanceMethod:customRESTMethod httpMethod:httpVerb]; return [[self getRelevantConfig] makeRequest:httpVerb requestBody:body route:route sync:error orAsync:nil]; } - (void) remoteRequest:(NSString *)httpVerb method:(NSString *)customRESTMethod body:(id)body async:(NSRHTTPCompletionBlock)completionBlock { - NSString *route = [self routeForInstanceMethod:customRESTMethod httpVerb:httpVerb]; + NSString *route = [self routeForInstanceMethod:customRESTMethod httpMethod:httpVerb]; [[self getRelevantConfig] makeRequest:httpVerb requestBody:body route:route sync:nil orAsync:completionBlock]; } @@ -888,16 +883,11 @@ - (void) remoteRequest:(NSString *)httpVerb method:(NSString *)customRESTMethod - (id) remoteRequest:(NSString *)httpVerb method:(NSString *)customRESTMethod error:(NSError **)error { - //done again so it can be tested before converting to JSON - [self assertCanSendInstanceRequestOnVerb:httpVerb]; - return [self remoteRequest:httpVerb method:customRESTMethod body:[self remoteDictionaryRepresentationWrapped:YES] error:error]; } - (void) remoteRequest:(NSString *)httpVerb method:(NSString *)customRESTMethod async:(NSRHTTPCompletionBlock)completionBlock { - [self assertCanSendInstanceRequestOnVerb:httpVerb]; - [self remoteRequest:httpVerb method:customRESTMethod body:[self remoteDictionaryRepresentationWrapped:YES] async:completionBlock]; } diff --git a/nsrails/Tests/NSRAsserts.h b/nsrails/Tests/NSRAsserts.h index 00f6f4e..288a4b5 100644 --- a/nsrails/Tests/NSRAsserts.h +++ b/nsrails/Tests/NSRAsserts.h @@ -29,7 +29,7 @@ + (NSRPropertyCollection *) propertyCollection; - (NSRPropertyCollection *) propertyCollection; -- (NSString *) routeForInstanceMethod:(NSString *)route httpVerb:(NSString *)str; +- (NSString *) routeForInstanceMethod:(NSString *)route httpMethod:(NSString *)str; + (NSString *) routeForControllerMethod:(NSString *)route; + (NSString *) typeForProperty:(NSString *)prop; diff --git a/nsrails/Tests/NSRRemoteObject.m b/nsrails/Tests/NSRRemoteObject.m index ab7e0b6..e0e959d 100644 --- a/nsrails/Tests/NSRRemoteObject.m +++ b/nsrails/Tests/NSRRemoteObject.m @@ -372,11 +372,11 @@ - (void) test_routes // Instance Empty *smth = [[Empty alloc] init]; - STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); + STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); smth.remoteID = [NSNumber numberWithInt:1]; - STAssertEqualObjects([smth routeForInstanceMethod:nil httpVerb:verb], @"empties/1", @"Nil instance route failed"); - STAssertEqualObjects([smth routeForInstanceMethod:@"action" httpVerb:verb], @"empties/1/action", @"Instance route failed"); + STAssertEqualObjects([smth routeForInstanceMethod:nil httpMethod:verb], @"empties/1", @"Nil instance route failed"); + STAssertEqualObjects([smth routeForInstanceMethod:@"action" httpMethod:verb], @"empties/1/action", @"Instance route failed"); } - (void) test_routes_with_prefixes @@ -391,18 +391,18 @@ - (void) test_routes_with_prefixes Prefixer *smth = [[Prefixer alloc] init]; STAssertNil([smth NSRUseResourcePrefixMethods], @"Should have nil allowed array"); - STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); + STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); smth.remoteID = [NSNumber numberWithInt:1]; - STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation is nil"); + STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation is nil"); smth.empty = [[Empty alloc] init]; - STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation has a nil remoteID"); + STAssertThrowsSpecificNamed([smth routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation has a nil remoteID"); smth.empty.remoteID = [NSNumber numberWithInt:15]; - STAssertEqualObjects([smth routeForInstanceMethod:nil httpVerb:verb], @"empties/15/prefixers/1", @"Nil instance route failed"); - STAssertEqualObjects([smth routeForInstanceMethod:@"action" httpVerb:verb], @"empties/15/prefixers/1/action", @"Instance route failed"); + STAssertEqualObjects([smth routeForInstanceMethod:nil httpMethod:verb], @"empties/15/prefixers/1", @"Nil instance route failed"); + STAssertEqualObjects([smth routeForInstanceMethod:@"action" httpMethod:verb], @"empties/15/prefixers/1/action", @"Instance route failed"); // Now double nested + custom names @@ -418,12 +418,12 @@ - (void) test_routes_with_prefixes NSRAssertEqualArraysNoOrder([smth2 NSRUseResourcePrefixMethods], NSRArray(@"GET", @"patch")); - STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); + STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); smth2.remoteID = [NSNumber numberWithInt:15]; - STAssertEqualObjects([smth2 routeForInstanceMethod:nil httpVerb:@"DELETE"], @"premans/15", @"Should be normal for non-included"); - STAssertEqualObjects([smth2 routeForInstanceMethod:@"something" httpVerb:@"DELETE"], @"premans/15/something", @"Should be normal for non-included"); + STAssertEqualObjects([smth2 routeForInstanceMethod:nil httpMethod:@"DELETE"], @"premans/15", @"Should be normal for non-included"); + STAssertEqualObjects([smth2 routeForInstanceMethod:@"something" httpMethod:@"DELETE"], @"premans/15/something", @"Should be normal for non-included"); for (int i = 0; i < 2; i++) { @@ -436,24 +436,24 @@ - (void) test_routes_with_prefixes smth2.thePrefixer = nil; // Instance - STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); + STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should have been an exception getting instance route if nil remoteID"); smth2.remoteID = [NSNumber numberWithInt:1]; - STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation is nil"); + STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation is nil"); smth2.thePrefixer = [[Prefixer alloc] init]; - STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation has a nil remoteID"); + STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should still crash, because 'empty' relation has a nil remoteID"); smth2.thePrefixer.remoteID = [NSNumber numberWithInt:15]; - STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should STILL crash, because 'thePrefixer' relation has a nil empty"); + STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should STILL crash, because 'thePrefixer' relation has a nil empty"); smth2.thePrefixer.empty = [[Empty alloc] init]; - STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpVerb:verb], NSException, NSRNullRemoteIDException, @"Should STILL crash, because 'thePrefixer' relation's empty has a nil remoteID"); + STAssertThrowsSpecificNamed([smth2 routeForInstanceMethod:nil httpMethod:verb], NSException, NSRNullRemoteIDException, @"Should STILL crash, because 'thePrefixer' relation's empty has a nil remoteID"); smth2.thePrefixer.empty.remoteID = [NSNumber numberWithInt:23]; - STAssertEqualObjects([smth2 routeForInstanceMethod:nil httpVerb:verb], @"empties/23/prefixers/15/premans/1", @"Nil instance route failed"); - STAssertEqualObjects([smth2 routeForInstanceMethod:@"action" httpVerb:verb], @"empties/23/prefixers/15/premans/1/action", @"Instance route failed"); + STAssertEqualObjects([smth2 routeForInstanceMethod:nil httpMethod:verb], @"empties/23/prefixers/15/premans/1", @"Nil instance route failed"); + STAssertEqualObjects([smth2 routeForInstanceMethod:@"action" httpMethod:verb], @"empties/23/prefixers/15/premans/1/action", @"Instance route failed"); } }