Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added array mapping transformer and refactored JSON array transformer #248

Merged
merged 10 commits into from

2 participants

@dcaunt

See #191

If this looks good I can add tests. All of the tests for mtl_JSONArrayTransformerWithModelClass: continue to work without any changes.

Some detail in the error key NSLocalizedDescriptionKey returned on mtl_JSONArrayTransformerWithModelClass:'s failure is now lost but we could check for an error in the array mapping transformer and modify the error message.

Unfortunately the diff looks pretty crazy for adding a new method.

@robb
Owner

Maybe its simpler doing a proper NSValueTransformer subclass rather than having two huge blocks?

@dcaunt

@robb How do you want me to implement that, can you be more specific?

@robb
Owner

I was thinking it could make sense to subclass NSValueTransformer and implement -transformedValue:success:error: there rather than using Mantle's block based transformer. That could end up more readable.

We'd maybe still want a +mtl_arrayMappingTransformerWithTransformer: convenience method, so I'm not sure if it's worth it

@dcaunt

I can refactor if there's a better way, though not using Mantle's block based transformer makes it more difficult to support both reversible and non-reversible transformers.

@robb
Owner

good point :+1:

...SValueTransformer+MTLPredefinedTransformerAdditions.m
((19 lines not shown))
- };
-
- *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
- }
- *success = NO;
- return nil;
++ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer {
+ NSParameterAssert(transformer != nil);
+
+ id (^forwardBlock)(NSArray *values, BOOL *success, NSError **error) = ^ id (NSArray *values, BOOL *success, NSError **error) {
+ if (values == nil) return nil;
+
+ if (![values isKindOfClass:NSArray.class]) {
+ if (error != NULL) {
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform non-array type", @""),
@robb Owner
robb added a note

the whitespace looks kinda off here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.m
((197 lines not shown))
}
-
- return dictionaries;
- }];
+
+ return transformedValues;
+ };
+ }
+ if (reverseBlock) {
@robb Owner
robb added a note

this should be (reverseBlock != nil)

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

I think this is on the right track, feel free to add tests

@dcaunt
...SValueTransformer+MTLPredefinedTransformerAdditions.h
@@ -46,6 +46,17 @@
// array elements back and forth.
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass;
+// An optionally reversible transformer which applies the given transformer to
+// each element of an array
@robb Owner
robb added a note

I think there is a full stop missing at the end of the line here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.h
@@ -46,6 +46,17 @@
// array elements back and forth.
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass;
+// An optionally reversible transformer which applies the given transformer to
+// each element of an array
+//
+// transformer - The transformer to apply to each element. If the transformer
+// is reversible, the transformer returned by this method will be
+// reversible.
+//
+// Returns a transformer which applies a transformation to each element of an
+// array
@robb Owner
robb added a note

I think there is a full stop missing at the end of the line here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.m
((127 lines not shown))
};
-
+
@robb Owner
robb added a note

Trailing whitespace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.m
((78 lines not shown))
};
-
+
@robb Owner
robb added a note

Trailing whitespace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.m
((208 lines not shown))
}
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary {
NSParameterAssert(dictionary != nil);
NSParameterAssert(dictionary.count == [[NSSet setWithArray:dictionary.allValues] count]);
-
+
@robb Owner
robb added a note

Trailing whitespace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.m
((223 lines not shown))
- NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not find associated value", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected %1$@ to contain a value for %2$@", @""), dictionary, key],
- MTLTransformerErrorHandlingInputValueErrorKey : key
- };
-
- *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
+ transformerUsingForwardBlock:^ id (id <NSCopying> key, BOOL *success, NSError **error) {
+ if (key == nil) key = NSNull.null;
+
+ id result = dictionary[key];
+
+ if (result == nil) {
+ if (error != NULL) {
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not find associated value", @""),
@robb Owner
robb added a note

Can you tweak the indentation here and in the reverse block?

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

Ah, sorry, hadn't realized this wasn't ready for review yet

@robb robb added the enhancement label
@robb robb added this to the 2.0 milestone
@robb
Owner

Looks good, is this ready to go?

@dcaunt

Still need to add some tests but the implementation is done.

@dcaunt

@robb I've added some tests but I'm a bit rusty on testing so let me know if you have any feedback

MantleTests/MTLPredefinedTransformerAdditionsSpec.m
@@ -171,6 +171,60 @@
});
});
+describe(@"array mapping transformer", ^{
+ __block NSValueTransformer *transformer;
+ __block NSArray *URLStrings;
@robb Owner
robb added a note

Since the URLs and strings are immutable, I think we could do something like:

NSArray *URLStrings = @[
    @"https://github.com",
    @"https://github.com/MantleFramework",
    @"https://apple.com]
];

NSArray *URLs = @[
    [NSURL URLwithString:@"https://github.com"],
    [NSURL URLwithString:@"https://github.com/MantleFramework"],
    [NSURL URLwithString:@"https://apple.com"]
];
@dcaunt
dcaunt added a note

Good point, I've made a new commit

@robb Owner
robb added a note

Can you also move them out of the beforeEach block and remove the __block qualifier?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
MantleTests/MTLPredefinedTransformerAdditionsSpec.m
((20 lines not shown))
+ expect(URL).notTo.beNil();
+
+ [mutableURLs addObject:URL];
+ }
+ URLs = [mutableURLs copy];
+
+ transformer = [NSValueTransformer mtl_arrayMappingTransformerWithTransformer:appliedTransformer];
+ expect(transformer).notTo.beNil();
+ });
+
+ it(@"should apply the transformer to each element", ^{
+ expect([transformer transformedValue:URLStrings]).to.equal(URLs);
+ });
+
+ it(@"should apply the transformer to each element in reverse", ^{
+ expect([transformer.class allowsReverseTransformation]).to.beTruthy();
@robb Owner
robb added a note

If the compiler let's you, this should be transformer.class.allowsReverseTransformation.

@dcaunt
dcaunt added a note

Unfortunately it doesn't

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

What are your thoughts on using nested describe blocks here for readability?

E.g.:

describe(@"+mtl_arrayMappingTransformerWithTransformer:", ^{
    describe(@"when called with a non-reversible transformer", ^{
        it(@"should not allow reverse transformation", ^{
            // check the allowsReverseTransformation flag
        });

        it(@"should apply the transformer", ^{
            // ...

            expect([transformer transformedValue:URLStrings]).to.equal(URLs);
        });
    });

    describe(@"when called with a reversible transformer", ^{
        it(@"should allow reverse transformation", ^{
            // check the allowsReverseTransformation flag
        });

        it(@"should apply the transformer in both directions", ^{
            // ...

            NSArray *transformed = [transformer transformedValue:URLStrings];

            expect(transformed).to.equal(URLs);

            expect([transformer reverseTransformedValue:transformed]).to.equal(URLStrings);
        });
    });
});
@robb robb self-assigned this
@dcaunt

I think it's a big improvement. The tests are a little more verbose than some of the other transformer tests, but I think that's no bad thing.

MantleTests/MTLPredefinedTransformerAdditionsSpec.m
@@ -171,6 +171,67 @@
});
});
+describe(@"array mapping transformer", ^{
@robb Owner
robb added a note

Can you make this +mtl_arrayMappingTransformerWithTransformer:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...SValueTransformer+MTLPredefinedTransformerAdditions.h
@@ -46,6 +46,17 @@
// array elements back and forth.
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass;
+// An optionally reversible transformer which applies the given transformer to
+// each element of an array.
+//
+// transformer - The transformer to apply to each element. If the transformer
+// is reversible, the transformer returned by this method will be
+// reversible.
@robb Owner
robb added a note

… This argument must not be nil.

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

:boom:

@robb robb merged commit ecf3d76 into Mantle:2.0-development
@dcaunt dcaunt deleted the dcaunt:array-mapping-transformer branch
@robb robb was unassigned by dcaunt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 22, 2014
  1. @dcaunt

    Added array mapping transformer and refactored mtl_JSONArrayTransform…

    dcaunt authored
    …erWithModelClass: to use it
Commits on Feb 26, 2014
  1. @dcaunt

    Whitespace fixes

    dcaunt authored
  2. @dcaunt

    Check reverseBlock is not nil

    dcaunt authored
Commits on Mar 1, 2014
  1. @dcaunt
Commits on Mar 3, 2014
  1. @dcaunt
Commits on Mar 8, 2014
  1. @dcaunt
Commits on Mar 9, 2014
  1. @dcaunt

    Improved test readability

    dcaunt authored
  2. @dcaunt
  3. @dcaunt
  4. @dcaunt
This page is out of date. Refresh to see the latest.
View
12 Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.h
@@ -46,10 +46,22 @@ extern NSString * const MTLBooleanValueTransformerName;
// array elements back and forth.
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass;
+// An optionally reversible transformer which applies the given transformer to
+// each element of an array.
+//
+// transformer - The transformer to apply to each element. If the transformer
+// is reversible, the transformer returned by this method will be
+// reversible. This argument must not be nil.
+//
+// Returns a transformer which applies a transformation to each element of an
+// array.
++ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer;
+
// A reversible value transformer to transform between the keys and objects of a
// dictionary.
//
// dictionary - The dictionary whose keys and values we should transform between.
+// This argument must not be nil.
//
// Can for example be used for transforming between enum values and their string
// representation.
View
259 Mantle/NSValueTransformer+MTLPredefinedTransformerAdditions.m
@@ -150,67 +150,80 @@ + (void)load {
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_JSONArrayTransformerWithModelClass:(Class)modelClass {
id<MTLTransformerErrorHandling> dictionaryTransformer = [self mtl_JSONDictionaryTransformerWithModelClass:modelClass];
+
+ return [self mtl_arrayMappingTransformerWithTransformer:dictionaryTransformer];
+}
- return [MTLValueTransformer
- transformerUsingForwardBlock:^ id (NSArray *dictionaries, BOOL *success, NSError **error) {
- if (dictionaries == nil) return nil;
-
- if (![dictionaries isKindOfClass:NSArray.class]) {
- if (error != NULL) {
-
- NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON array to model array", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), dictionaries],
- MTLTransformerErrorHandlingInputValueErrorKey : dictionaries
- };
-
- *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
- }
- *success = NO;
- return nil;
++ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_arrayMappingTransformerWithTransformer:(NSValueTransformer *)transformer {
+ NSParameterAssert(transformer != nil);
+
+ id (^forwardBlock)(NSArray *values, BOOL *success, NSError **error) = ^ id (NSArray *values, BOOL *success, NSError **error) {
+ if (values == nil) return nil;
+
+ if (![values isKindOfClass:NSArray.class]) {
+ if (error != NULL) {
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform non-array type", @""),
+ NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), values],
+ MTLTransformerErrorHandlingInputValueErrorKey: values
+ };
+
+ *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
}
-
- NSMutableArray *models = [NSMutableArray arrayWithCapacity:dictionaries.count];
- for (id JSONDictionary in dictionaries) {
- if (JSONDictionary == NSNull.null) {
- [models addObject:NSNull.null];
- continue;
- }
-
- if (![JSONDictionary isKindOfClass:NSDictionary.class]) {
+ *success = NO;
+ return nil;
+ }
+
+ NSMutableArray *transformedValues = [NSMutableArray arrayWithCapacity:values.count];
+ NSInteger index = -1;
+ for (id value in values) {
+ index++;
+ if (value == NSNull.null) {
+ [transformedValues addObject:NSNull.null];
+ continue;
+ }
+
+ id transformedValue = nil;
+ if ([transformer conformsToProtocol:@protocol(MTLTransformerErrorHandling)]) {
+ NSError *underlyingError = nil;
+ transformedValue = [(id<MTLTransformerErrorHandling>)transformer transformedValue:value success:success error:&underlyingError];
+
+ if (*success == NO) {
if (error != NULL) {
NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON array to model array", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSDictionary or an NSNull, got: %@.", @""), JSONDictionary],
- MTLTransformerErrorHandlingInputValueErrorKey : JSONDictionary
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform array", @""),
+ NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Could not transform value at index %d", @""), index],
+ NSUnderlyingErrorKey: underlyingError,
+ MTLTransformerErrorHandlingInputValueErrorKey: values
};
*error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
}
- *success = NO;
return nil;
}
-
- id model = [dictionaryTransformer transformedValue:JSONDictionary success:success error:error];
-
- if (*success == NO) return nil;
-
- if (model == nil) continue;
-
- [models addObject:model];
+ } else {
+ transformedValue = [transformer transformedValue:value];
}
-
- return models;
+
+ if (transformedValue == nil) continue;
+
+ [transformedValues addObject:transformedValue];
}
- reverseBlock:^ id (NSArray *models, BOOL *success, NSError **error) {
- if (models == nil) return nil;
-
- if (![models isKindOfClass:NSArray.class]) {
+
+ return transformedValues;
+ };
+
+ id (^reverseBlock)(NSArray *values, BOOL *success, NSError **error) = nil;
+ if (transformer.class.allowsReverseTransformation) {
+ reverseBlock = ^ id (NSArray *values, BOOL *success, NSError **error) {
+ if (values == nil) return nil;
+
+ if (![values isKindOfClass:NSArray.class]) {
if (error != NULL) {
NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert model array to JSON array", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), models],
- MTLTransformerErrorHandlingInputValueErrorKey : models
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform non-array type", @""),
+ NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected an NSArray, got: %@.", @""), values],
+ MTLTransformerErrorHandlingInputValueErrorKey: values
};
*error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
@@ -218,39 +231,51 @@ + (void)load {
*success = NO;
return nil;
}
-
- NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:models.count];
- for (id model in models) {
- if (model == NSNull.null) {
- [dictionaries addObject:NSNull.null];
+
+ NSMutableArray *transformedValues = [NSMutableArray arrayWithCapacity:values.count];
+ NSInteger index = -1;
+ for (id value in values) {
+ index++;
+ if (value == NSNull.null) {
+ [transformedValues addObject:NSNull.null];
continue;
}
-
- if (![model isKindOfClass:MTLModel.class]) {
- if (error != NULL) {
- NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not convert JSON array to model array", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected a MTLModel or an NSNull, got: %@.", @""), model],
- MTLTransformerErrorHandlingInputValueErrorKey : model
- };
-
- *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
+
+ id transformedValue = nil;
+ if ([transformer respondsToSelector:@selector(reverseTransformedValue:success:error:)]) {
+ NSError *underlyingError = nil;
+ transformedValue = [(id<MTLTransformerErrorHandling>)transformer reverseTransformedValue:value success:success error:&underlyingError];
+
+ if (*success == NO) {
+ if (error != NULL) {
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not transform array", @""),
+ NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Could not transform value at index %d", @""), index],
+ NSUnderlyingErrorKey: underlyingError,
+ MTLTransformerErrorHandlingInputValueErrorKey: values
+ };
+
+ *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
+ }
+ return nil;
}
- *success = NO;
- return nil;
+ } else {
+ transformedValue = [transformer reverseTransformedValue:value];
}
-
- NSDictionary *dict = [dictionaryTransformer reverseTransformedValue:model success:success error:error];
-
- if (*success == NO) return nil;
-
- if (dict == nil) continue;
-
- [dictionaries addObject:dict];
+
+ if (transformedValue == nil) continue;
+
+ [transformedValues addObject:transformedValue];
}
-
- return dictionaries;
- }];
+
+ return transformedValues;
+ };
+ }
+ if (reverseBlock != nil) {
+ return [MTLValueTransformer transformerUsingForwardBlock:forwardBlock reverseBlock:reverseBlock];
+ } else {
+ return [MTLValueTransformer transformerUsingForwardBlock:forwardBlock];
+ }
}
+ (NSValueTransformer<MTLTransformerErrorHandling> *)mtl_valueMappingTransformerWithDictionary:(NSDictionary *)dictionary {
@@ -258,52 +283,52 @@ + (void)load {
NSParameterAssert(dictionary.count == [[NSSet setWithArray:dictionary.allValues] count]);
return [MTLValueTransformer
- transformerUsingForwardBlock:^ id (id <NSCopying> key, BOOL *success, NSError **error) {
- if (key == nil) key = NSNull.null;
-
- id result = dictionary[key];
-
- if (result == nil) {
- if (error != NULL) {
- NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not find associated value", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected %1$@ to contain a value for %2$@", @""), dictionary, key],
- MTLTransformerErrorHandlingInputValueErrorKey : key
- };
-
- *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
+ transformerUsingForwardBlock:^ id (id <NSCopying> key, BOOL *success, NSError **error) {
+ if (key == nil) key = NSNull.null;
+
+ id result = dictionary[key];
+
+ if (result == nil) {
+ if (error != NULL) {
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not find associated value", @""),
+ NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected %1$@ to contain a value for %2$@", @""), dictionary, key],
+ MTLTransformerErrorHandlingInputValueErrorKey : key
+ };
+
+ *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
+ }
+ *success = NO;
+ return nil;
}
- *success = NO;
- return nil;
+
+ return result;
}
-
- return result;
- }
- reverseBlock:^ id (id value, BOOL *success, NSError **error) {
- __block id result = nil;
- [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id anObject, BOOL *stop) {
- if ([value isEqual:anObject]) {
- result = key;
- *stop = YES;
+ reverseBlock:^ id (id value, BOOL *success, NSError **error) {
+ __block id result = nil;
+ [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id anObject, BOOL *stop) {
+ if ([value isEqual:anObject]) {
+ result = key;
+ *stop = YES;
+ }
+ }];
+
+ if (result == nil) {
+ if (error != NULL) {
+ NSDictionary *userInfo = @{
+ NSLocalizedDescriptionKey: NSLocalizedString(@"Could not find associated key", @""),
+ NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected %1$@ to contain a key that maps to %2$@", @""), dictionary, value],
+ MTLTransformerErrorHandlingInputValueErrorKey : value
+ };
+
+ *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
+ }
+ *success = NO;
+ return nil;
}
+
+ return result;
}];
-
- if (result == nil) {
- if (error != NULL) {
- NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Could not find associated key", @""),
- NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedString(@"Expected %1$@ to contain a key that maps to %2$@", @""), dictionary, value],
- MTLTransformerErrorHandlingInputValueErrorKey : value
- };
-
- *error = [NSError errorWithDomain:MTLTransformerErrorHandlingErrorDomain code:MTLTransformerErrorHandlingErrorInvalidInput userInfo:userInfo];
- }
- *success = NO;
- return nil;
- }
-
- return result;
- }];
}
@end
View
61 MantleTests/MTLPredefinedTransformerAdditionsSpec.m
@@ -171,6 +171,67 @@
});
});
+describe(@"+mtl_arrayMappingTransformerWithTransformer:", ^{
+ __block NSValueTransformer *transformer;
+
+ NSArray *URLStrings = @[
+ @"https://github.com/",
+ @"https://github.com/MantleFramework",
+ @"http://apple.com"
+ ];
+ NSArray *URLs = @[
+ [NSURL URLWithString:@"https://github.com/"],
+ [NSURL URLWithString:@"https://github.com/MantleFramework"],
+ [NSURL URLWithString:@"http://apple.com"]
+ ];
+
+ describe(@"when called with a reversible transformer", ^{
+ beforeEach(^{
+ NSValueTransformer *appliedTransformer = [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
+ transformer = [NSValueTransformer mtl_arrayMappingTransformerWithTransformer:appliedTransformer];
+ expect(transformer).notTo.beNil();
+ });
+
+ it(@"should allow reverse transformation", ^{
+ expect([transformer.class allowsReverseTransformation]).to.beTruthy();
+ });
+
+ it(@"should apply the transformer to each element", ^{
+ expect([transformer transformedValue:URLStrings]).to.equal(URLs);
+ });
+
+ it(@"should apply the transformer to each element in reverse", ^{
+ expect([transformer reverseTransformedValue:URLs]).to.equal(URLStrings);
+ });
+ });
+
+ describe(@"when called with a non-reversible transformer", ^{
+ beforeEach(^{
+ NSValueTransformer *appliedTransformer = [MTLValueTransformer transformerUsingForwardBlock:^(NSString *str, BOOL *success, NSError **error) {
+ return [NSURL URLWithString:str];
+ }];
+ transformer = [NSValueTransformer mtl_arrayMappingTransformerWithTransformer:appliedTransformer];
+ expect(transformer).notTo.beNil();
+ });
+
+ it(@"should not allow reverse transformation", ^{
+ expect([transformer.class allowsReverseTransformation]).to.beFalsy();
+ });
+
+ it(@"should apply the transformer to each element", ^{
+ expect([transformer transformedValue:URLStrings]).to.equal(URLs);
+ });
+ });
+
+ itShouldBehaveLike(MTLTransformerErrorExamples, ^{
+ return @{
+ MTLTransformerErrorExamplesTransformer: transformer,
+ MTLTransformerErrorExamplesInvalidTransformationInput: NSNull.null,
+ MTLTransformerErrorExamplesInvalidReverseTransformationInput: NSNull.null
+ };
+ });
+});
+
describe(@"value mapping transformer", ^{
__block NSValueTransformer *transformer;
Something went wrong with that request. Please try again.