Commit 30e09834 by Brent Gulanowski

Add fix to handling of many-to-many encoding, and test to verify it.

Refactor and fix in `-buy_JSONForValue:` as well as other refactoring. Move a comment to where it is most applicable.
parent b3c7e09a
......@@ -34,11 +34,12 @@
#import "NSPropertyDescription+BUYAdditions.h"
#import "TestModel.h"
static NSString * const RootEntity = @"Root";
static NSString * const BirdEntity = @"Bird";
static NSString * const BranchEntity = @"Branch";
static NSString * const LeafEntity = @"Leaf";
static NSString * const NestEntity = @"Nest";
static NSString * const BirdEntity = @"Bird";
static NSString * const ResearchEntity = @"Researcher";
static NSString * const RootEntity = @"Root";
@interface NSIndexSet (BUYTestAdditions)
+ (instancetype)indexSetWithIndexes:(NSArray *)indexes;
......@@ -228,6 +229,13 @@ static NSString * const BirdEntity = @"Bird";
XCTAssertEqualObjects(actual, branch.leaves);
}
- (void)testManyToManyRelationship
{
Researcher *researcher = [self.modelManager buy_objectWithEntityName:ResearchEntity JSONDictionary:nil];
NSRelationshipDescription *researchersRelationship = [self relationshipWithName:@"researchers" forEntity:BirdEntity];
XCTAssertNil([researchersRelationship buy_JSONForValue:[NSSet setWithObject:researcher]]);
}
- (void)testEntityIsPrivate
{
NSEntityDescription *forestEntity = [self entityForName:[Forest entityName]];
......
......@@ -9,6 +9,7 @@
<entry key="key" value="value"/>
</userInfo>
</relationship>
<relationship name="researchers" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Researcher" inverseName="birds" inverseEntity="Researcher" syncable="YES"/>
</entity>
<entity name="Branch" representedClassName="Branch" syncable="YES">
<attribute name="ornaments" optional="YES" attributeType="Transformable" syncable="YES">
......@@ -50,6 +51,10 @@
</relationship>
<relationship name="branch" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Branch" inverseName="nest" inverseEntity="Branch" syncable="YES"/>
</entity>
<entity name="Researcher" representedClassName="Researcher" syncable="YES">
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="birds" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Bird" inverseName="researchers" inverseEntity="Bird" syncable="YES"/>
</entity>
<entity name="Root" representedClassName="Root" syncable="YES">
<attribute name="age" optional="YES" attributeType="Decimal" defaultValueString="0.0" syncable="YES"/>
<attribute name="identifier" optional="YES" attributeType="Integer 64" defaultValueString="0" syncable="YES"/>
......@@ -64,11 +69,12 @@
<relationship name="forest" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Forest" inverseName="trees" inverseEntity="Forest" syncable="YES"/>
</entity>
<elements>
<element name="Bird" positionX="151" positionY="111" width="128" height="90"/>
<element name="Bird" positionX="146" positionY="111" width="128" height="103"/>
<element name="Branch" positionX="-288" positionY="-3" width="128" height="105"/>
<element name="Forest" positionX="-718" positionY="57" width="128" height="58"/>
<element name="Leaf" positionX="-72" positionY="-18" width="128" height="90"/>
<element name="Nest" positionX="-72" positionY="126" width="128" height="90"/>
<element name="Root" positionX="-504" positionY="-18" width="128" height="133"/>
<element name="Forest" positionX="-477" positionY="137" width="128" height="58"/>
<element name="Researcher" positionX="-288" positionY="81" width="128" height="75"/>
</elements>
</model>
\ No newline at end of file
......@@ -20,11 +20,12 @@
@property (nonatomic, strong) TestModelManager *modelManager;
@end
@class Leaf, Nest, Root;
@class Leaf, Nest, Researcher, Root;
@interface Bird : TestModel
@property (nonatomic) NSNumber *identifier;
@property (nonatomic) NSString *colour;
@property (nonatomic) NSSet<Researcher *> *researchers;
+ (instancetype)birdWithIdentifier:(NSNumber *)identifier;
@end
......@@ -49,6 +50,11 @@
@property (nonatomic) Branch *branch;
@end
@interface Researcher : TestModel
@property (nonatomic) NSString *name;
@property (nonatomic) NSSet<Bird *> *birds;
@end
@interface Root : TestModel
@property (nonatomic) NSNumber *identifier;
@property (nonatomic) NSDecimalNumber *age;
......
......@@ -200,9 +200,7 @@
- (NSUInteger)hash
{
NSUInteger hash = self.date.hash;
hash = (hash << 5) ^ self.tags.hash;
return hash;
return (self.date.hash << 5) ^ self.tags.hash;
}
@end
......@@ -218,11 +216,22 @@
- (NSUInteger)hash
{
NSUInteger hash = self.eggCount.hash;
if (self.bird) {
hash = (hash << 5) ^ self.bird.hash;
}
return hash;
return (self.branch.hash << 5) ^ (7231UL + self.eggCount.unsignedIntegerValue);
}
@end
@implementation Researcher
- (BOOL)isEqual:(Researcher *)object
{
return ([super isEqual:object] &&
[self.name isEqual:object.name]);
}
- (NSUInteger)hash
{
return self.name.hash;
}
@end
......@@ -241,12 +250,7 @@
- (NSUInteger)hash
{
NSUInteger hash = self.identifier.hash;
hash = (hash << 5) ^ self.age.hash;
hash = (hash << 5) ^ self.name.hash;
hash = (hash << 5) ^ self.url.hash;
hash = (hash << 5) ^ self.branches.hash;
return hash;
return self.identifier.hash;
}
@end
......@@ -200,14 +200,6 @@ static NSString *JSONValueTransformerNameForAttributeType(NSAttributeType type)
// model -> JSON
- (id)buy_JSONForObject:(NSObject<BUYObject> *)object
{
// JSON generation for a relationship depends on the rules defined in the model.
// The model can explicitly specify using an `id` encoding.
// Alternately, if the relationship is compatible, encode the entire object.
// We do not encode related objects unless three conditions are satisfied:
// 1. the relationship is not many-to-many
// 2. the inverse relationship is not an ownership relationship
// (this is inferred from the `NSCascadeDeleteRule` used by owning objects)
// 3. the relationship is to a "private" entity (not known to the API)
id json = nil;
if (!self.inverseRelationship || self.inverseRelationship.allowsInverseEncoding) {
json = [self.destinationEntity buy_JSONForObject:object];
......@@ -238,8 +230,7 @@ static NSString *JSONValueTransformerNameForAttributeType(NSAttributeType type)
// (ordered)set (of models) -> JSON
- (NSArray *)buy_JSONForCollection:(id)collection
{
NSArray *array = [self buy_arrayForCollection:collection];
return [self.destinationEntity buy_JSONForArray:array];
return [self.destinationEntity buy_JSONForArray:[self buy_arrayForCollection:collection]];
}
#pragma mark - Property Additions Overrides
......@@ -250,31 +241,38 @@ static NSString *JSONValueTransformerNameForAttributeType(NSAttributeType type)
// The logic for decoding JSON is slightly different for to-one and to-many relationships.
// NOTE: by default, without a caching system, inverse relationships are not supported.
id value = nil;
if ([JSON buy_isValidObject]) {
if (self.isToMany) {
return [self buy_collectionForJSON:JSON modelManager:object.modelManager];
value = [self buy_collectionForJSON:JSON modelManager:object.modelManager];
}
else {
return [self buy_objectForJSON:JSON modelManager:object.modelManager];
value = [self buy_objectForJSON:JSON modelManager:object.modelManager];
}
}
else {
return nil;
}
return value;
}
- (id)buy_JSONForValue:(id)value
{
// JSON generation for a relationship depends on the rules defined in the model.
// The model can explicitly specify using an `id` encoding.
// Alternately, if the relationship is compatible, encode the entire object.
// We do not encode related objects unless three conditions are satisfied:
// 1. the relationship is not many-to-many
// 2. the inverse relationship is not an ownership relationship
// (this is inferred from the `NSCascadeDeleteRule` used by owning objects)
// 3. the relationship is to a "private" entity (not known to the API)
id json = nil;
if (self.encodesIdInJSON) {
json = [value valueForKey:NSStringFromSelector(@selector(identifier))];
}
else if (self.toMany && ! self.manyToMany) {
json = [self buy_JSONForCollection:value];
}
else {
else if (!self.toMany) {
json = [self buy_JSONForObject:value];
}
else if (!self.manyToMany) {
json = [self buy_JSONForCollection:value];
}
return json;
}
......
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