Skip to content

Instantly share code, notes, and snippets.

@alloy
Forked from subdigital/factories.m
Created February 21, 2012 17:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alloy/1877485 to your computer and use it in GitHub Desktop.
Save alloy/1877485 to your computer and use it in GitHub Desktop.
A test object factory potential implementation
// Omitted is a NSDictionary category which adds -[NSDictionary merge:dict]
@interface PersonFactory : Factory
@end
@implementation PersonFactory
- (NSDictionary *)validAttrs;
{
return @{ @"name":@"Test Person %d", @"email":@"person-%d@example.com" };
}
@end
@interface CustomerFactory : PersonFactory
@end
@implementation CustomerFactory
- (NSDictionary *)validAttrs;
{
return [[super validAttrs] merge:@{ @"type":@"customer" }];
}
- (NSDictionary *)activeAttrs;
{
return [[self validAttrs] merge:@{ @"status":@"active" }];
}
- (void)associate:(Customer *)customer withInvoice:(Invoice *)invoice;
{
// obviously this can be as simple/hard as necessary
customer.invoice = invoice;
}
@end
// give me customer attrs
NSDictionary *customerAttrs = [Factory(Customer) plan:1];
// give me an array of customer attrs with active status
NSArray *customersAttrs = [Factory(Customer) plan:2 type:@"active"];
// give me an unsaved customer with type active
Customer *costumer = [Factory(Customer) build:1 type:@"active"];
// give me an array of saved customers with custom attrs
NSArray *costumers = [Factory(Customer) create:2 attrs:@{ @"status":@"suspended" }];
// associate customer with invoice (yes, this needs a NSObject category :-/)
[customer associateTo:[Factory(Invoice) build:1]];
// associate customers with invoice
[customers associateTo:[Factory(Invoice) build:1]];
// associate invoices with a customer
[[Factory(Invoice) create:20] associateTo:customer];
@alloy
Copy link
Author

alloy commented Feb 21, 2012

The Person class may or may not exist, in this case it contains behavior that would be shared with other subject types in the system.

@alloy
Copy link
Author

alloy commented Feb 21, 2012

The library would use reflection to choose the proper attrs method. I.e. by default use validAttrs, or if a type is given it would use typeAttrs.

@alloy
Copy link
Author

alloy commented Feb 21, 2012

Every instance increases a counter that will be used against any value in attrs dictionaries, if it contains %d, or something along those lines.

@subdigital
Copy link

Customer *costumer = [Factory(Customer) build:1 type:@"active"];

what are those parameters?

Are you intending to parse the selector and perform the magic on the valid attributes?

Also, build versus create ? Are you assuming NSManagedObject subclasses?

@alloy
Copy link
Author

alloy commented Feb 21, 2012

The plan:/build:/create: parts of the selector is the amount of instances you want, type: indicates the attars to use, which by default is validAttrs.

@interface Factory
- plan:(NSUInteger)amount; // always uses validAttrs
- plan:(NSUInteger)amount type:(NSString *)attrsType; // indicates the ‘attars’ method to use, e.g. ‘active’ expands to the activeAttrs method
- plan:(NSUInteger)amount attrs:(NSDictionary *)customAttrs; // these are merged with validAttrs
- plan:(NSUInteger)amount type:(NSString *)attrsType attrs:(NSDictionary *)customAttrs; // these are merged with the attrs define in attrsType
@end

Yes, in this case I’m using NSManagedObject subclasses, but the same principle applies to most persistence layers and in case the model is not something that’s persisted, than just using the build variants will suffice, because these will just assign the properties and should work on any class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment