Skip to content

Commit

Permalink
Use delegate pattern for canceled login.
Browse files Browse the repository at this point in the history
Move isNewRecord to model level.
Create rkcurl script.
  • Loading branch information
Jeremy Ellison committed Jan 20, 2011
1 parent 8894346 commit b20b78e
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 33 deletions.
Expand Up @@ -8,8 +8,9 @@

#import <Foundation/Foundation.h>
#import <Three20/Three20.h>
#import "DBLoginOrSignUpViewController.h"

@interface DBAuthenticatedTableViewController : TTTableViewController {
@interface DBAuthenticatedTableViewController : TTTableViewController <DBLoginOrSignupViewControllerDelegate> {
BOOL _requiresLoggedInUser;
NSNumber* _requiredUserID;
}
Expand Down
Expand Up @@ -13,7 +13,6 @@ @implementation DBAuthenticatedTableViewController

- (void)viewDidUnload {
[[NSNotificationCenter defaultCenter] removeObserver:self name:DBUserDidLoginNotification object:nil];
// [[NSNotificationCenter defaultCenter] removeObserver:self name:kLoginCanceledNotificationName object:nil];
}

- (void)loadView {
Expand All @@ -23,40 +22,35 @@ - (void)loadView {
if (_requiresLoggedInUser) {
BOOL isAuthenticated = NO;
if (_requiredUserID &&
[DBUser currentUser].singleAccessToken &&
// Put current user id first because it might be nil.
[[DBUser currentUser] isLoggedIn] &&
[[DBUser currentUser].userID isEqualToNumber:_requiredUserID]) {
isAuthenticated = YES;
// TODO: Move this isAuthenticated logic into the model!
} else if (_requiredUserID == nil &&
[DBUser currentUser].singleAccessToken &&
[DBUser currentUser] != nil) {
[[DBUser currentUser] isLoggedIn]) {
isAuthenticated = YES;
}

if (!isAuthenticated) {
// Register for login succeeded notification. populate view.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDidLogin:) name:DBUserDidLoginNotification object:nil];

// Register for login canceled notification. pop view controller.
// TODO: Not sure what's up with the cancel...
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loginCanceled:) name:kLoginCanceledNotificationName object:nil];

TTOpenURL(@"db://login");

DBLoginOrSignUpViewController* loginViewController = (DBLoginOrSignUpViewController*)TTOpenURL(@"db://login");
loginViewController.delegate = self;
}
}
}

- (void)userDidLogin:(NSNotification*)note {
// check user id is allowed.
// check to ensure the user that logged in is allowed to acces this controller.
if (_requiredUserID && [[DBUser currentUser].userID isEqualToNumber:_requiredUserID]) {
[self invalidateModel];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
}

- (void)loginCanceled:(NSNotification*)note {
- (void)loginControllerDidCancel:(DBLoginOrSignUpViewController*)loginController {
[self.navigationController popViewControllerAnimated:YES];
}

Expand Down
Expand Up @@ -11,6 +11,9 @@
#import <RestKit/RestKit.h>
#import "DBUser.h"

@protocol DBLoginOrSignupViewControllerDelegate;


@interface DBLoginOrSignUpViewController : TTTableViewController <UITextFieldDelegate, DBUserAuthenticationDelegate> {
UIBarButtonItem* _signupOrLoginButtonItem;
BOOL _showingSignup;
Expand All @@ -19,6 +22,17 @@
UITextField* _passwordField;
UITextField* _passwordConfirmationField;
UITextField* _emailField;

id<DBLoginOrSignupViewControllerDelegate> _delegate;
}

@property (nonatomic, assign) id<DBLoginOrSignupViewControllerDelegate> delegate;


@end

@protocol DBLoginOrSignupViewControllerDelegate

- (void)loginControllerDidCancel:(DBLoginOrSignUpViewController*)loginController;

@end
Expand Up @@ -10,6 +10,8 @@

@implementation DBLoginOrSignUpViewController

@synthesize delegate = _delegate;

- (id)initWithNavigatorURL:(NSURL *)URL query:(NSDictionary *)query {
if (self = [super initWithNavigatorURL:URL query:query]) {
self.title = @"Login";
Expand Down Expand Up @@ -88,8 +90,7 @@ - (void)createModel {

- (void)cancelButtonWasPressed:(id)sender {
[self dismissModalViewControllerAnimated:YES];
// TODO: Do we need cancel login support???
// [[NSNotificationCenter defaultCenter] postNotificationName:kLoginCanceledNotificationName object:self];
[_delegate loginControllerDidCancel:self];
}

- (void)signupOrLoginButtonItemWasPressed:(id)sender {
Expand Down
Expand Up @@ -9,10 +9,11 @@
#import <Foundation/Foundation.h>
#import "DBAuthenticatedTableViewController.h"
#import "DBPost.h"
#import "DBTopic.h"

@interface DBPostTableViewController : DBAuthenticatedTableViewController <RKObjectLoaderDelegate, TTTextEditorDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
DBPost* _post;
NSNumber* _topicID;
DBTopic* _topic;

TTTextEditor* _bodyTextEditor;
TTImageView* _currentAttachmentImageView;
Expand Down
Expand Up @@ -23,15 +23,15 @@ - (id)initWithPostID:(NSString*)postID {
- (id)initWithTopicID:(NSString*)topicID {
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
// TODO: Why are we using topic ID here?
_topicID = [[NSNumber numberWithInt:[topicID intValue]] retain];
_topic = [[DBTopic objectWithPrimaryKeyValue:topicID] retain];
}

return self;
}

- (void)dealloc {
TT_RELEASE_SAFELY(_post);
TT_RELEASE_SAFELY(_topicID);
TT_RELEASE_SAFELY(_topic);

[super dealloc];
}
Expand All @@ -55,7 +55,7 @@ - (void)loadView {

if (nil == _post) {
_post = [[DBPost object] retain];
_post.topicID = _topicID;
_post.topicID = _topic.topicID;
}

_requiresLoggedInUser = YES;
Expand Down
Expand Up @@ -24,11 +24,6 @@ - (void)dealloc {
[super dealloc];
}

// TODO: Move this into the model...
- (BOOL)isNewRecord {
return [[_topic topicID] intValue] == 0;
}

- (void)viewDidUnload {
TT_RELEASE_SAFELY(_topicNameField);
}
Expand All @@ -42,7 +37,7 @@ - (void)loadView {
}

_requiresLoggedInUser = YES;
if (![self isNewRecord]) {
if (![_topic isNewRecord]) {
_requiredUserID = _topic.userID;
}

Expand All @@ -58,7 +53,7 @@ - (void)createModel {
_topicNameField.text = _topic.name;
[items addObject:[TTTableControlItem itemWithCaption:@"Name" control:_topicNameField]];

if ([self isNewRecord]) {
if ([_topic isNewRecord]) {
self.title = @"New Topic";
[items addObject:[TTTableButton itemWithText:@"Create" delegate:self selector:@selector(createButtonWasPressed:)]];
} else {
Expand Down Expand Up @@ -98,7 +93,6 @@ - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)obje
}

- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
// TODO: TTAlert or create a DBErrorAlert helper?
[[[[UIAlertView alloc] initWithTitle:@"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease] show];
}

Expand Down
Expand Up @@ -106,4 +106,9 @@
*/
@property (nonatomic, retain) UIImage* newAttachment;

/**
* Returns true if the record has not yet been saved/synced with the server.
*/
- (BOOL)isNewRecord;

@end
Expand Up @@ -100,4 +100,8 @@ + (NSDictionary*)relationshipToPrimaryKeyPropertyMappings {
return params;
}

- (BOOL)isNewRecord {
return [[self postID] intValue] == 0;
}

@end
Expand Up @@ -63,4 +63,9 @@
*/
@property (nonatomic, retain) NSNumber* userID;

/**
* Returns true if the record has not yet been saved/synced with the server.
*/
- (BOOL)isNewRecord;

@end
Expand Up @@ -60,4 +60,8 @@ + (NSString*)primaryKeyProperty {
return @"topicID";
}

- (BOOL)isNewRecord {
return [[self topicID] intValue] == 0;
}

@end
Expand Up @@ -19,7 +19,6 @@ extern NSString* const DBRestKitBaseURL;

// TODO: See if we can eliminate or abstract this further
extern NSString* const kObjectCreatedUpdatedOrDestroyedNotificationName;

/**
* Server Environments for conditional compilation
*/
Expand Down
Expand Up @@ -19,3 +19,4 @@

// TODO: Eliminate
NSString* const kObjectCreatedUpdatedOrDestroyedNotificationName = @"kObjectCreatedUpdatedOrDestroyedNotificationName";

Expand Up @@ -12,14 +12,14 @@

@implementation DBManagedObjectCache

// TODO: Cleanup this code somehow...
- (NSArray*)fetchRequestsForResourcePath:(NSString*)resourcePath {
if ([resourcePath isEqualToString:@"/topics"]) {
NSFetchRequest* request = [DBTopic fetchRequest];
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
return [NSArray arrayWithObject:request];
}

// match on /topics/:id/posts
NSArray* components = [resourcePath componentsSeparatedByString:@"/"];
if ([components count] == 4 &&
Expand Down
Expand Up @@ -146,7 +146,7 @@

/* Begin PBXFileReference section */
1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
1D6058910D05DD3D006BFB54 /* DiscussionBoard-Development.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DiscussionBoard-Development.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1D6058910D05DD3D006BFB54 /* DiscussionBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DiscussionBoard.app; sourceTree = BUILT_PRODUCTS_DIR; };
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
25359D4212E3E0A4008BF33D /* libThree20.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libThree20.a; sourceTree = "<group>"; };
25359D4312E3E0A4008BF33D /* libThree20Core.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libThree20Core.a; sourceTree = "<group>"; };
Expand Down Expand Up @@ -534,7 +534,7 @@
19C28FACFE9D520D11CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
1D6058910D05DD3D006BFB54 /* DiscussionBoard-Development.app */,
1D6058910D05DD3D006BFB54 /* DiscussionBoard.app */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -1103,7 +1103,7 @@
);
name = DiscussionBoard;
productName = DiscussionBoard;
productReference = 1D6058910D05DD3D006BFB54 /* DiscussionBoard-Development.app */;
productReference = 1D6058910D05DD3D006BFB54 /* DiscussionBoard.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
Expand Down
49 changes: 49 additions & 0 deletions Scripts/rkcurl
@@ -0,0 +1,49 @@
#!/usr/bin/ruby

input = ""
ARGV.each do |b|
input = b
end

if input == ""
puts "
This tool parses RestKit logging output and turns it into a curl request so you can see what is going on easier. Simply copy and paste the 'Headers' and 'Sending' lines out of the XCode Console and pass them in to this tool to see the curl request & response.
This is an easy way to see the output from an RKRequest.
USAGE:\n./rkcurl \"2011-01-20 11:40:07.122 DiscussionBoard[25362:40b] Headers: {
Accept = \"application/json\";
\"X-User-Access-Token\" = csitBupAGxaNVVX6XSo;
}
2011-01-20 11:40:07.123 DiscussionBoard[25362:40b] Sending GET request to URL http://discussionboard.heroku.com/topics/4/posts. HTTP Body:
\"
"
exit 0
end

headersString = input.match(/.*Headers: \{(.*)\}/m)[1]
headers = []

headersString.each_line do |line|
next if line.strip.size == 0
headers << line.strip.gsub(";", "").gsub(" = ", ": ")
end

method = input.match(/Sending (.*) request to/m)[1]
url = input.match(/URL (.*)\./m)[1]

data = nil
dataMatch = input.match(/HTTP Body: (.*)\n/m)
data = dataMatch[1] if dataMatch

command = "curl -X #{method} "
command << "-d \"#{data.gsub('"', '\"')}\" " if data
for header in headers
command << "-H \"#{header.gsub('"', '\"')}\" "
end
command << url

puts command

output = `#{command}`

puts output

0 comments on commit b20b78e

Please sign in to comment.