Commit 34374ba6 by Dima Bart

Adjust BUYAccountCredentials interface to improve discoverability.

- add string constants for valid credential item keys
- add factory methods to eliminate the need to using keys explicitly
- simplify implementation and validation logic
parent 922d7a64
...@@ -154,9 +154,11 @@ ...@@ -154,9 +154,11 @@
NSData *data = [NSJSONSerialization dataWithJSONObject:credentials.JSONRepresentation options:0 error:nil]; NSData *data = [NSJSONSerialization dataWithJSONObject:credentials.JSONRepresentation options:0 error:nil];
return [self putRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { return [self putRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
if (json && !error) { NSString *email = json[@"customer"][@"email"];
BUYAccountCredentialItem *emailItem = [BUYAccountCredentialItem itemWithKey:@"email" value:json[@"customer"][@"email"]]; if (email && !error) {
credentials[@"email"] = emailItem; BUYAccountCredentialItem *emailItem = [BUYAccountCredentialItem itemEmailWithValue:email];
[credentials setCredentialItem:emailItem];
[self loginCustomerWithCredentials:credentials callback:block]; [self loginCustomerWithCredentials:credentials callback:block];
} }
else { else {
...@@ -171,9 +173,11 @@ ...@@ -171,9 +173,11 @@
NSData *data = [NSJSONSerialization dataWithJSONObject:credentials.JSONRepresentation options:0 error:nil]; NSData *data = [NSJSONSerialization dataWithJSONObject:credentials.JSONRepresentation options:0 error:nil];
return [self putRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) { return [self putRequestForURL:components.URL body:data completionHandler:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
if (json && !error) { NSString *email = json[@"customer"][@"email"];
BUYAccountCredentialItem *emailItem = [BUYAccountCredentialItem itemWithKey:@"email" value:json[@"customer"][@"email"]]; if (email && !error) {
credentials[@"email"] = emailItem; BUYAccountCredentialItem *emailItem = [BUYAccountCredentialItem itemEmailWithValue:email];
[credentials setCredentialItem:emailItem];
[self loginCustomerWithCredentials:credentials callback:block]; [self loginCustomerWithCredentials:credentials callback:block];
} }
else { else {
......
...@@ -25,40 +25,53 @@ ...@@ -25,40 +25,53 @@
// //
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** extern NSString * const BUYAccountFirstNameKey;
* Intended for storing a collection of credential items representing individual values extern NSString * const BUYAccountLastNameKey;
*/ extern NSString * const BUYAccountEmailKey;
extern NSString * const BUYAccountPasswordKey;
extern NSString * const BUYAccountPasswordConfirmationKey;
@class BUYAccountCredentialItem; @class BUYAccountCredentialItem;
@interface BUYAccountCredentials : NSObject
NS_ASSUME_NONNULL_BEGIN /**
* Encapsulates user's credentials represented by BUYAccountCredentialItem
* objects.
*/
@interface BUYAccountCredentials : NSObject
+ (BUYAccountCredentials *)credentialsWithItems:(NSArray<BUYAccountCredentialItem *> *)items; @property (nonatomic, assign, readonly, getter=isValid) BOOL valid;
+ (BUYAccountCredentials *)credentialsWithItemKeys:(NSArray<NSString *> *)keys; @property (nonatomic, strong, readonly) NSDictionary *JSONRepresentation;
@property (readonly) NSDictionary *JSONRepresentation; + (BUYAccountCredentials *)credentialsWithItems:(nullable NSArray<BUYAccountCredentialItem *> *)items;
@property (nonatomic, readonly, getter=isValid) BOOL valid; - (instancetype)initWithItems:(nullable NSArray<BUYAccountCredentialItem *> *)items;
- (BUYAccountCredentialItem *)objectForKeyedSubscript:(NSString *)key; - (void)setCredentialItems:(NSArray<BUYAccountCredentialItem *> *)items;
- (void)setObject:(BUYAccountCredentialItem *)obj forKeyedSubscript:(NSString *)key; - (void)setCredentialItem:(BUYAccountCredentialItem *)item;
@end @end
/** /**
* Represents a key and KVC-validatable value * Represents a single for user's credentials such as
* email or password.
*/ */
@interface BUYAccountCredentialItem : NSObject @interface BUYAccountCredentialItem : NSObject
+ (instancetype)itemWithKey:(NSString *)key value:(NSString *)value; @property (nonatomic, assign, readonly, getter=isValid) BOOL valid;
@property (nonatomic, strong, readonly) NSString *key;
@property (nonatomic, strong, readonly) NSString *value;
@property (nonatomic, getter=isValid) BOOL valid; + (instancetype)itemEmailWithValue:(NSString *)value;
@property (nonatomic, strong) NSString *key; + (instancetype)itemFirstNameWithValue:(NSString *)value;
@property (nonatomic, strong) NSString *value; + (instancetype)itemLastNameWithValue:(NSString *)value;
+ (instancetype)itemPasswordWithValue:(NSString *)value;
+ (instancetype)itemPasswordConfirmationWithValue:(NSString *)value;
NS_ASSUME_NONNULL_END + (instancetype)itemWithKey:(NSString *)key value:(NSString *)value;
- (instancetype)initWithKey:(NSString *)key value:(NSString *)value;
@end @end
NS_ASSUME_NONNULL_END
\ No newline at end of file
...@@ -26,94 +26,123 @@ ...@@ -26,94 +26,123 @@
#import "BUYAccountCredentials.h" #import "BUYAccountCredentials.h"
@class BUYAccountCredentialItem; NSString * const BUYAccountFirstNameKey = @"first_name";
NSString * const BUYAccountLastNameKey = @"last_name";
NSString * const BUYAccountEmailKey = @"email";
NSString * const BUYAccountPasswordKey = @"password";
NSString * const BUYAccountPasswordConfirmationKey = @"password_confirmation";
#pragma mark - BUYAccountCredentials -
@interface BUYAccountCredentials() @interface BUYAccountCredentials()
@property (strong, nonatomic) NSMutableDictionary<NSString *, BUYAccountCredentialItem *> *items; @property (strong, nonatomic) NSMutableDictionary<NSString *, BUYAccountCredentialItem *> *items;
@end @end
@implementation BUYAccountCredentials @implementation BUYAccountCredentials
+ (BUYAccountCredentials *)credentialsWithItems:(NSArray<BUYAccountCredentialItem *> *)items + (BUYAccountCredentials *)credentialsWithItems:(NSArray<BUYAccountCredentialItem *> *)items
{ {
BUYAccountCredentials *credentials = [BUYAccountCredentials new]; return [[BUYAccountCredentials alloc] initWithItems:items];
NSMutableDictionary *keyedItems = [NSMutableDictionary dictionary]; }
for (BUYAccountCredentialItem *item in items) {
keyedItems[item.key] = item; - (instancetype)initWithItems:(NSArray<BUYAccountCredentialItem *> *)items
{
self = [super init];
if (self) {
_items = [NSMutableDictionary new];
if (items.count > 0) {
[self setCredentialItems:items];
}
} }
credentials.items = keyedItems; return self;
return credentials;
} }
+ (BUYAccountCredentials *)credentialsWithItemKeys:(NSArray<NSString *> *)keys #pragma mark - Accessors -
- (BOOL)isValid
{ {
NSMutableArray *items = [NSMutableArray array]; __block BOOL valid = YES;
for (NSString *key in keys) { [self.items enumerateKeysAndObjectsUsingBlock:^(NSString *key, BUYAccountCredentialItem *item, BOOL * _Nonnull stop) {
BUYAccountCredentialItem *item = [BUYAccountCredentialItem itemWithKey:key value:@""]; if (!item.isValid) {
[items addObject:item]; valid = NO;
*stop = YES;
}
}];
return valid;
}
- (void)setCredentialItems:(NSArray<BUYAccountCredentialItem *> *)items
{
NSAssert(items, @"BUYAccountCredentialItem array cannot be nil.");
for (BUYAccountCredentialItem *item in items) {
[self setCredentialItem:item];
} }
return [BUYAccountCredentials credentialsWithItems:items];
} }
- (void)setCredentialItem:(BUYAccountCredentialItem *)item
{
NSAssert(item, @"BUYAccountCredentialItem cannot be nil.");
self.items[item.key] = item;
}
#pragma mark - Serialization -
- (NSDictionary *)JSONRepresentation - (NSDictionary *)JSONRepresentation
{ {
__block NSMutableDictionary *customer = [NSMutableDictionary dictionary]; __block NSMutableDictionary *customer = [NSMutableDictionary dictionary];
[self.items enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, BUYAccountCredentialItem * _Nonnull obj, BOOL * _Nonnull stop) { [self.items enumerateKeysAndObjectsUsingBlock:^(NSString *key, BUYAccountCredentialItem *obj, BOOL *stop) {
customer[key] = obj.value; customer[key] = obj.value;
}]; }];
return @{ @"customer": customer }; return @{ @"customer": customer };
} }
- (BOOL)validateValue:(inout id _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable __autoreleasing *)outError @end
{
return [self.items[inKey] validateValue:ioValue forKey:inKey error:outError];
}
- (BUYAccountCredentialItem *)objectForKeyedSubscript:(NSString *)key #pragma mark - BUYAccountCredentialItem -
@implementation BUYAccountCredentialItem
#pragma mark - Init -
+ (instancetype)itemEmailWithValue:(NSString *)value
{ {
return self.items[key]; return [[BUYAccountCredentialItem alloc] initWithKey:BUYAccountEmailKey value:value];
} }
- (void)setObject:(BUYAccountCredentialItem *)obj forKeyedSubscript:(NSString *)key + (instancetype)itemFirstNameWithValue:(NSString *)value
{ {
self.items[key] = obj; return [[BUYAccountCredentialItem alloc] initWithKey:BUYAccountFirstNameKey value:value];
} }
- (BOOL)validationForKey:(NSString *)key + (instancetype)itemLastNameWithValue:(NSString *)value
{ {
return [self.items[key] isValid]; return [[BUYAccountCredentialItem alloc] initWithKey:BUYAccountLastNameKey value:value];
} }
- (BOOL)isValid + (instancetype)itemPasswordWithValue:(NSString *)value
{ {
__block BOOL valid = YES; return [[BUYAccountCredentialItem alloc] initWithKey:BUYAccountPasswordKey value:value];
[self.items enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, BUYAccountCredentialItem * _Nonnull obj, BOOL * _Nonnull stop) {
valid = valid && [obj isValid];
}];
return valid;
} }
@end + (instancetype)itemPasswordConfirmationWithValue:(NSString *)value
@implementation BUYAccountCredentialItem
+ (instancetype)itemWithKey:(NSString *)key value:(NSString *)value
{ {
BUYAccountCredentialItem *item = [BUYAccountCredentialItem new]; return [[BUYAccountCredentialItem alloc] initWithKey:BUYAccountPasswordConfirmationKey value:value];
item.key = key;
item.value = value;
return item;
} }
- (NSString *)value + (instancetype)itemWithKey:(NSString *)key value:(NSString *)value
{ {
return _value ?: @""; return [[BUYAccountCredentialItem alloc] initWithKey:key value:value];
} }
- (BOOL)validateValue:(inout id _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable __autoreleasing *)outError - (instancetype)initWithKey:(NSString *)key value:(NSString *)value
{ {
self.value = *ioValue; self = [super init];
self.valid = self.value.length > 0; if (self) {
return [self isValid]; NSAssert(value, @"Cannot initialize BUYAccountCredentialItem with nil value.");
_key = key;
_value = value;
_valid = value.length > 0;
}
return self;
} }
@end @end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment