diff --git a/Code/CoreData/RKManagedObject.m b/Code/CoreData/RKManagedObject.m index 8893f69f..5ea51200 100644 --- a/Code/CoreData/RKManagedObject.m +++ b/Code/CoreData/RKManagedObject.m @@ -157,7 +157,7 @@ return [self valueForKey:[[self class] primaryKeyProperty]]; } -- (NSDictionary*)paramsForSerialization { +- (id)paramsForSerialization { NSMutableDictionary* params = [NSMutableDictionary dictionary]; for (NSString* elementName in [[self class] elementToPropertyMappings]) { NSString* propertyName = [[[self class] elementToPropertyMappings] objectForKey:elementName]; diff --git a/Code/ObjectMapping/RKObject.m b/Code/ObjectMapping/RKObject.m index cdfeb628..a13c8ab9 100644 --- a/Code/ObjectMapping/RKObject.m +++ b/Code/ObjectMapping/RKObject.m @@ -23,7 +23,7 @@ return [[self new] autorelease]; } -- (NSDictionary*)paramsForSerialization { +- (id)paramsForSerialization { NSMutableDictionary* params = [NSMutableDictionary dictionary]; for (NSString* elementName in [[self class] elementToPropertyMappings]) { NSString* propertyName = [[[self class] elementToPropertyMappings] objectForKey:elementName]; diff --git a/Code/ObjectMapping/RKObjectMappable.h b/Code/ObjectMapping/RKObjectMappable.h index e5e21857..dddf3b61 100644 --- a/Code/ObjectMapping/RKObjectMappable.h +++ b/Code/ObjectMapping/RKObjectMappable.h @@ -7,6 +7,8 @@ * */ +@protocol RKRequestSerializable; + /** * Must be implemented by all classes utilizing the RKModelMapper to map REST * responses to domain model classes @@ -43,7 +45,7 @@ * will encode these parameters into a serialization format (form encoded, JSON, etc). This is * required to use putObject: and postObject: for updating and creating remote object representations. */ -- (NSDictionary*)paramsForSerialization; +- (id)paramsForSerialization; /** * Must return a new autoreleased instance of the model class ready for mapping. Used to initialize the model diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBLoginViewController.m b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBLoginViewController.m index 4ce7f40b..ec8807b9 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBLoginViewController.m +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBLoginViewController.m @@ -78,6 +78,7 @@ _passwordField.returnKeyType = UIReturnKeyGo; } self.dataSource = [TTListDataSource dataSourceWithItems:items]; + [_usernameField becomeFirstResponder]; } diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostTableViewController.m b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostTableViewController.m index dc6b0d4c..159b0a02 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostTableViewController.m +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostTableViewController.m @@ -8,6 +8,7 @@ #import "DBPostTableViewController.h" #import +#import "DBUser.h" @implementation DBPostTableViewController @@ -51,9 +52,6 @@ } _requiresLoggedInUser = YES; - if (![self isNewRecord]) { - _requiredUserID = _post.userID; - } [super loadView]; @@ -61,40 +59,56 @@ _bodyTextEditor.font = [UIFont systemFontOfSize:12]; _bodyTextEditor.autoresizesToText = NO; _bodyTextEditor.delegate = self; + _bodyTextEditor.text = _post.body; } - (void)createModel { + BOOL isAuthorizedUser = [[DBUser currentUser].userID isEqualToNumber:_post.userID] || [self isNewRecord]; + NSMutableArray* items = [NSMutableArray array]; - _bodyTextEditor.text = _post.body; - - [items addObject:[TTTableControlItem itemWithCaption:@"" control:(UIControl*)_bodyTextEditor]]; - // Attachment item. - if (_newAttachment) { - // has new attachment. show it. allow update. - [items addObject:[TTTableImageItem itemWithText:@"Tap to Replace Image" imageURL:@"" defaultImage:_newAttachment URL:@"db://updateAttachment"]]; - } else if (![[_post attachmentPath] isWhitespaceAndNewlines]) { - // Has existing attachment. allow replace - NSString* url = [NSString stringWithFormat:@"%@%@", [RKObjectManager sharedManager].client.baseURL, _post.attachmentPath]; - [items addObject:[TTTableImageItem itemWithText:@"Tap to Replace Image" imageURL:url defaultImage:nil URL:@"db://updateAttachment"]]; + if (isAuthorizedUser) { + [items addObject:[TTTableControlItem itemWithCaption:@"" control:(UIControl*)_bodyTextEditor]]; + if (_newAttachment) { + // has new attachment. show it. allow update. + [items addObject:[TTTableImageItem itemWithText:@"Tap to Replace Image" imageURL:@"" defaultImage:_newAttachment URL:@"db://updateAttachment"]]; + } else if (![[_post attachmentPath] isWhitespaceAndNewlines]) { + // Has existing attachment. allow replace + NSString* url = [NSString stringWithFormat:@"%@%@", [RKObjectManager sharedManager].client.baseURL, _post.attachmentPath]; + [items addObject:[TTTableImageItem itemWithText:@"Tap to Replace Image" imageURL:url defaultImage:nil URL:@"db://updateAttachment"]]; + } else { + // has no attachment. allow new one. + [items addObject:[TTTableTextItem itemWithText:@"Tap to Add Image" URL:@"db://updateAttachment"]]; + } } else { - // has no attachment. allow new one. - [items addObject:[TTTableTextItem itemWithText:@"Tap to Add Image" URL:@"db://updateAttachment"]]; + [items addObject:[TTTableLongTextItem itemWithText:_post.body]]; + NSString* url = [NSString stringWithFormat:@"%@%@", [RKObjectManager sharedManager].client.baseURL, _post.attachmentPath]; + [items addObject:[TTTableImageItem itemWithText:@"" imageURL:url URL:nil]]; } if ([self isNewRecord]) { self.title = @"New Post"; [items addObject:[TTTableButton itemWithText:@"Create" delegate:self selector:@selector(createButtonWasPressed:)]]; } else { - self.title = @"Edit Post"; - [items addObject:[TTTableButton itemWithText:@"Update" delegate:self selector:@selector(updateButtonWasPressed:)]]; - [items addObject:[TTTableButton itemWithText:@"Delete" delegate:self selector:@selector(destroyButtonWasPressed:)]]; + if (isAuthorizedUser) { + self.title = @"Edit Post"; + [items addObject:[TTTableButton itemWithText:@"Update" delegate:self selector:@selector(updateButtonWasPressed:)]]; + [items addObject:[TTTableButton itemWithText:@"Delete" delegate:self selector:@selector(destroyButtonWasPressed:)]]; + } else { + self.title = @"Post"; + } } - self.dataSource = [TTListDataSource dataSourceWithItems:items]; + NSString* byLine = @""; + if (![self isNewRecord]) { + NSString* username = (isAuthorizedUser ? @"me" : _post.username); + byLine = [NSString stringWithFormat:@"posted by %@", username]; + } + self.dataSource = [TTSectionedDataSource dataSourceWithArrays:byLine, items, nil]; } - (void)updateAttachment { + [_bodyTextEditor resignFirstResponder]; UIImagePickerController* controller = [[[UIImagePickerController alloc] init] autorelease]; controller.delegate = self; [self presentModalViewController:controller animated:YES]; diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostsTableViewController.m b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostsTableViewController.m index 678d263e..538ea56f 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostsTableViewController.m +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Controllers/DBPostsTableViewController.m @@ -71,7 +71,12 @@ for(DBPost* post in model.objects) { NSString* url = [NSString stringWithFormat:@"db://posts/%@", post.postID]; - [postItems addObject:[TTTableLongTextItem itemWithText:post.body URL:url]]; + NSString* imageURL = [NSString stringWithFormat:@"%@%@", [RKObjectManager sharedManager].client.baseURL, + post.attachmentPath]; + TTTableImageItem* item = [TTTableImageItem itemWithText:post.body + imageURL:imageURL + URL:url]; + [postItems addObject:item]; } self.dataSource = [TTSectionedDataSource dataSourceWithArrays:@"Topic", diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/DiscussionBoardAppDelegate.m b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/DiscussionBoardAppDelegate.m index 1704e191..6ddd245f 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/DiscussionBoardAppDelegate.m +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/DiscussionBoardAppDelegate.m @@ -9,6 +9,7 @@ #import "DiscussionBoardAppDelegate.h" #import #import +#import #import #import #import "DBTopicsTableViewController.h" @@ -52,13 +53,16 @@ static NSString* const kAccessTokenHeaderField = @"HTTP_USER_ACCESS_TOKEN"; // Set Up Router RKDynamicRouter* router = [[[RKDynamicRouter alloc] init] autorelease]; +// RKRailsRouter* router = [[[RKRailsRouter alloc] init] autorelease]; [router routeClass:[DBUser class] toResourcePath:@"/signup" forMethod:RKRequestMethodPOST]; [router routeClass:[DBUser class] toResourcePath:@"/login" forMethod:RKRequestMethodPUT]; +// [router setModelName:@"topic" forClass:[DBTopic class]]; [router routeClass:[DBTopic class] toResourcePath:@"/topics" forMethod:RKRequestMethodPOST]; [router routeClass:[DBTopic class] toResourcePath:@"/topics/(topicID)" forMethod:RKRequestMethodPUT]; [router routeClass:[DBTopic class] toResourcePath:@"/topics/(topicID)" forMethod:RKRequestMethodDELETE]; +// [router setModelName:@"post" forClass:[DBPost class]]; [router routeClass:[DBPost class] toResourcePath:@"/topics/(topicID)/posts" forMethod:RKRequestMethodPOST]; [router routeClass:[DBPost class] toResourcePath:@"/topics/(topicID)/posts/(postID)" forMethod:RKRequestMethodPUT]; [router routeClass:[DBPost class] toResourcePath:@"/topics/(topicID)/posts/(postID)" forMethod:RKRequestMethodDELETE]; @@ -89,9 +93,6 @@ static NSString* const kAccessTokenHeaderField = @"HTTP_USER_ACCESS_TOKEN"; NSLog(@"User: %@", user); [objectManager.client setValue:[DBUser currentUser].singleAccessToken forHTTPHeaderField:@"USER_ACCESS_TOKEN"]; - // Testing - TTOpenURL(@"db://posts/9"); - return YES; } diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.h b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.h index 97853d3f..c96e606b 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.h +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.h @@ -24,6 +24,7 @@ @property (nonatomic, retain) NSDate* updatedAt; @property (nonatomic, retain) NSNumber* userID; @property (nonatomic, retain) NSNumber* postID; +@property (nonatomic, retain) NSString* username; @property (nonatomic, retain) UIImage* newAttachment; diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.m b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.m index f0069102..dcd946d8 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.m +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBPost.m @@ -22,6 +22,7 @@ @dynamic updatedAt; @dynamic userID; @dynamic postID; +@dynamic username; @synthesize newAttachment = _newAttachment; @@ -38,6 +39,7 @@ @"attachment_path", @"attachmentPath", @"attachment_updated_at", @"attachmentUpdatedAt", @"body", @"body", + @"user_login", @"username", nil]; } @@ -45,17 +47,18 @@ return @"postID"; } -- (NSDictionary*)paramsForSerialization { +- (id)paramsForSerialization { RKParams* params = [RKParams params]; [params setValue:self.body forParam:@"post[body]"]; + NSLog(@"Self Body: %@", self.body); if (_newAttachment) { NSData* data = UIImagePNGRepresentation(_newAttachment); NSLog(@"Data Size: %d", [data length]); - [params setData:data MIMEType:@"application/octet-stream" forParam:@"topic[attachment]"]; + RKParamsAttachment* attachment = [params setData:data MIMEType:@"application/octet-stream" forParam:@"post[attachment]"]; + attachment.fileName = @"image.png"; } - // Suppress warning. todo: should this method return an by default? - return (NSDictionary*)params; + return params; } @end diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.h b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.h index eb74abb5..07c388be 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.h +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.h @@ -18,5 +18,6 @@ @property (nonatomic, retain) NSNumber* userID; @property (nonatomic, retain) NSDate* createdAt; @property (nonatomic, retain) NSDate* updatedAt; +@property (nonatomic, retain) NSString* username; @end diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.m b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.m index bdac5472..c37fbdf7 100644 --- a/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.m +++ b/Examples/RKDiscussionBoardExample/DiscussionBoard/Classes/Models/DBTopic.m @@ -15,6 +15,7 @@ @dynamic userID; @dynamic createdAt; @dynamic updatedAt; +@dynamic username; #pragma mark RKObjectMappable methods @@ -24,7 +25,8 @@ @"name",@"name", @"user_id",@"userID", @"created_at",@"createdAt", - @"updated_at",@"updatedAt", + @"updated_at",@"updatedAt", + @"user_login", @"username", nil]; } @@ -32,7 +34,7 @@ return @"topicID"; } -- (NSDictionary*)paramsForSerialization { +- (id)paramsForSerialization { return [NSDictionary dictionaryWithObjectsAndKeys: self.name, @"topic[name]", nil]; } diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/elements b/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/elements index 93250fa5..3d3ff91c 100644 Binary files a/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/elements and b/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/elements differ diff --git a/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/layout b/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/layout index b43c2ce3..7686034f 100644 Binary files a/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/layout and b/Examples/RKDiscussionBoardExample/DiscussionBoard/DataModel.xcdatamodel/layout differ diff --git a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/posts_controller.rb b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/posts_controller.rb index 82b33e55..0f97dc42 100644 --- a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/posts_controller.rb +++ b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/posts_controller.rb @@ -7,19 +7,19 @@ class PostsController < ApplicationController before_filter :requre_owner, :only => [:update, :destroy] index.response do |wants| - wants.json{ render :json => collection.to_json(:methods => :attachment_path) } + wants.json{ render :json => collection.to_json(:methods => [:attachment_path, :user_login]) } end create.response do |wants| - wants.json{ render :json => object.to_json(:methods => :attachment_path) } + wants.json{ render :json => object.to_json(:methods => [:attachment_path, :user_login]) } end update.response do |wants| - wants.json{ render :json => object.to_json(:methods => :attachment_path) } + wants.json{ render :json => object.to_json(:methods => [:attachment_path, :user_login]) } end destroy.response do |wants| wants.json{ render :json => {} } end show.response do |wants| - wants.json{ render :json => object.to_json(:methods => :attachment_path) } + wants.json{ render :json => object.to_json(:methods => [:attachment_path, :user_login]) } end create.before do diff --git a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/topics_controller.rb b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/topics_controller.rb index c1a1dabe..6813f177 100644 --- a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/topics_controller.rb +++ b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/controllers/topics_controller.rb @@ -5,19 +5,19 @@ class TopicsController < ApplicationController before_filter :requre_owner, :only => [:update, :destroy] index.response do |wants| - wants.json { render :json => collection } + wants.json { render :json => collection.to_json(:methods => :user_login) } end create.response do |wants| - wants.json{ render :json => object } + wants.json{ render :json => object.to_json(:methods => :user_login) } end update.response do |wants| - wants.json{ render :json => object } + wants.json{ render :json => object.to_json(:methods => :user_login) } end destroy.response do |wants| wants.json{ render :json => {} } end show.response do |wants| - wants.json{ render :json => object } + wants.json{ render :json => object.to_json(:methods => :user_login) } end create.before do diff --git a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/post.rb b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/post.rb index 0d064ce8..23976f82 100644 --- a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/post.rb +++ b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/post.rb @@ -7,4 +7,8 @@ class Post < ActiveRecord::Base attachment.url end + def user_login + user.login + end + end diff --git a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/topic.rb b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/topic.rb index 96264c4f..f06cfd6b 100644 --- a/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/topic.rb +++ b/Examples/RKDiscussionBoardExample/discussion_board_backend/app/models/topic.rb @@ -4,4 +4,8 @@ class Topic < ActiveRecord::Base validates_presence_of :name validates_presence_of :user + + def user_login + user.login + end end