FatFractal customer forums



Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - jonnycools

Pages: 1 [2] 3 4 5
16
NoServer Questions and Answers / Re: Delta Updates?
« on: March 22, 2014, 02:57:35 PM »
Supporting client side is nightmarish. All i'm looking for is possibly server side and via REST API.


17
NoServer Questions and Answers / Delta Updates?
« on: March 22, 2014, 12:46:28 PM »
how does updating an object work?

There are three options for a key

Its there
Its NULL
Its not there

So if my extension attempts to update just one key, could I strip out all the other keys and whats not in the PUT request won't get written as NULL

For example I have this Comment Object

CREATE OBJECTTYPE Comment (FFUser REFERENCE /FFUSER, message STRING, other NUMERIC)

Say I have an extension

Code: [Select]

exports.somefunction = function()
{

var comment = ff.getObjectAUri("...");

var save = new Object();

save.guid = comment.guid;

save.other = comment.other + 1;

ff.updateObj(save);

}


Here I'm specifically leaving out the message. The reason is I have certain fields on the object that are maintained by the server. I have concerns over race conditions. Say the client updates this object with an old version of other or the server updates the object with an old version of message.

I would understand the key with null says i removed it.

The key with a value means update

Would the absence of a key just do nothing. - So for clients on the do not serialize, these properties won't get overridden with old data.

Would this work with the REST API if a key just wasn't in the JSON?

18
Quote

I was referring to the idea of keeping a grabbag synced to a local collection. You said this wasn't their purpose.


Well fatfractal doesn't support arrays of references. Grabbags are supposed to serve that purpose. I will admit sometimes I wish they did. Right now Array are only for embedding the objects data directly in another object.

Keeping stuff synced is all up to you really. I'm finding that quite tiresome but it's just part of the job I suppose. I'm actually considering a hybrid coredata, ff mashup now.

Well I lean data molding the hard way. I swear I've remodeled my database like 20 times. It all depends on how you want to use it. It recommend modeling the relationships based on his you intend to use them rather that how they are inherently structured.

19
Really I could see that creating a retain cycle but an infinite loop, really?

Quote

Sure. But the framework can be aware of whether you changed the elements in the array or not. Things do get a little hairy here admittedly.


To be honest I'm having problems with this one myself. After the initial creating of the objects. Sometimes its hard to say whats changed, when I don't commit changes right away.

The only thing is should and can the framework do this via an NSMutableArray or would you still have to make that separate call (Tracking the contents of arrays can be a lot of overhead). Removing things is where problems crop up, how do I know somethings was taken out if I don't know it was there to begin with.

20
Quote

Except the documentation and some posts in here inform that this is an entirely valid and supported use-case. I can't argue against the notion that there may be another intended purpose though.


What is your use case?

Quote

Grabbags are of some interest to me since I am attempting to maintain to-many 2-way references in a similar way to what CoreData provides. This seems non-trivial, even using grabbags.


Are you trying to maintain explicit two way references? Do you really need it? I ask because you can use BackReferences and Alias to take advantage of the platform's built in method of meaning two way relationships. The only caveat is you on one side of the relationship you won't know its there until you query for it.

Take a parent to child relationship. It is common to declare a reference from child to parent. When retrieving a child its trivial to see who their parent is. However asking the parent who are your children isn't explicitly defined. Here you can use backReferences to find its child easily even as the platform maintains two way relationships for you.

Code: [Select]

<parent>/<guid>/BackReferences.<ChildrenCollection>.<parentReference>


In a previous release they added the ability to have alias be populated with the object. so when using the depthGB= in queries all alias would be retrieved as well. So the thats one way of getting two way relationships handled for you. Of course this extend to Grabbags both ways as well.

I glossed over this, but if you need further explanation here just ask.

Quote

Sure. But the framework can be aware of whether you changed the elements in the array or not. Things do get a little hairy here admittedly.


Now that's interesting. More on this in a bit.

Quote

This wouldn't really be keeping my code clean, as much as opting to reimplement the functionality of the SDK myself :). Aside from grabbag functionality, I haven't noticed any functionality in FF that bleeds in this way. That said, I've only been playing with it for the past week or so.


Now there's a scary thought, one I have contemplated.

21
Fellow user,

The issue here is scalability. Grabbags are designed to scale to thousands of relationships. These are not type of things you keep synced to local arrays. You usually retrieve the entities of Grabbags in paginated queries. Upon first creating an object things are great as the array may represent the compete set, but for any other type of operation it may not. Say I update an object with a grabbag but I don't have any objects in the array at update, maybe I chose not to retrieved them as I didn't need it. Does the server assume that you intend to have an empty grabbag. What I can say is that similar data structures are handled like this on other comparable BaaS services. The explicit need to make these calls is important. It also the only true way to prevent the user from having a special object to maintain these Grabbags, that in my opinion is more lock in, although there are some advantages.

The only true way to keep your code clean would bs not to use he SDK and go REST. This is as good as it gets when trying to maintain that no data type lock in.

22
NoServer Questions and Answers / Re: Event Handler Questions
« on: March 11, 2014, 09:59:28 AM »
!. The documentation isn't quite clear about this, I suspect one portion is outdated. However from experience retrieve handlers are supported, but are only POST. Meaning after it has been retrieved but before its returned the user

Code: [Select]

CREATE HANDLER handlerName POST ON /<Collection> Retrieve AS javascript:require('scripts/<fileNameWithoutTheDotjs>').functionName();


2. I believe you just through an exception

PS. This should be a PRE handler, not sure if POST would work here as the server does have a rollback feature for failed handlers

Code: [Select]

exports.updateCollection = function()
{

        var authorized = ...;

if (!authorized)
{

throw {statusCode:405, statusMessage:"user not allowed to edit object."};

}

}


23
Gary this was a problem Dave showed me how to solve before the forums existed. The issue here is an understanding of how the deserializer works.


So when you retrieve an object from a URI, be it an extension or a query the deserializer attempts to map the clazz the to the class.

If the object returned has a clazz and the client has registered a class to this clazz the object will be class mapped.

If the object returned doesn't have a clazz or you haven't class mapped it you get an NSDictionary.


Now your issue specifically is structured data.

So if the object at the first level has a clazz and its class mapped the deserializer will class mapped the object and look for potential objects at level two.

If the first level does not contain a clazz or ins't class mapped the serializer stops there.

So more specifically in your case you attempt to send an array with regular json objects to the client, so arrays will always produce an array and you get NSDictionaries at the second level and the deserializer will stop there. So your photo and metegameData objects don't get class mapped.

To fix this problem give the intermediary object a clazz and class map that clazz on the client side.

Javascript

Code: [Select]

function = ExtentionResponse()
{

this.clazz = "MinigameDataAndPhotosFromMatch";
this.minigameData = null;
this.photos = null;

}

var getMinigameDataAndPhotosFromMatch = function () {
var i, photoObjects, data, ff, r, d, guid, minigameData, result;

ff = require('ffef/FatFractal');
d = ff.getExtensionRequestData();
guid = d.httpParameters.guid;
r = ff.response();
result = [];
minigameData = ff.getArrayFromUri("/Match/" + guid + "/BackReferences.MinigameData.match");
for (var i = 0; i < minigameData.length; i++){

var minigameDataMeta = minigameData[i];

var photos = ff.getArrayFromUri("/MinigameData/" + minigameDataMeta.guid + "/BackReferences.Photo.minigameData");

                        var object = new ExtentionResponse();

                        object.minigameData = minigameData[i];

                        object.photos = photos;

result.push(object);

};

r.result = result;
};


I hope this helps, let me know if you need anything explained further

24
NoServer Questions and Answers / Re: user management
« on: February 28, 2014, 09:25:20 PM »
Interesting

Have you formally declared the new properties in your FDDL file for the FFUser ObjectType?

For example

Code: [Select]

CREATE OBJECTTYPE FFUser (userName STRING, firstName STRING, lastName STRING, email STRING, active BOOLEAN, authDomain STRING, scriptAuthService STRING, groups GRABBAG /FFUserGroup, notif_ids GRABBAG /FFNotificationID, imageData BYTEARRAY)


25
NoServer Questions and Answers / Re: user management
« on: February 28, 2014, 05:57:35 PM »
While I cannot address the blob issue, here's how you upload blobs after the object has been created in the backend.

You can call this method in the onComplete block of the register user.

Code: [Select]

[[FatFractal main] updateBlob:_imageData withMimeType:@"type" forObj:newUser memberName:@"imageData" onComplete:^(NSError *theErr, id theObj, NSHTTPURLResponse *theResponse) {
       
    }];


26
NoServer Questions and Answers / Re: user management
« on: February 27, 2014, 04:40:35 PM »
Unoffical response.

There are two approaches to creating custom users.

1) subclass FFUser

Here we simply create a subclass of FFUser, declare our custom properties and the all important thing is to register the subclass with FatFractal

Subclass

Code: [Select]

@import Foundation;

@interface CustomUser : FFUser

@property (nonatomic, strong) NSData * imageData;

@end


Register Subclass

Code: [Select]

FatFractal * ff = [[FatFractal alloc] initWithBaseUrl:@"https://...
       
[ff registerClass:[CustomUser class] forClazz:@"FFUser"]; //Most important step! Do this right after you initialize the FatFractal Instance!


Now all methods that return an FFUser will return an instance of CustomUser.

Feel free to formally declare the additional properties in the FDDL file

Code: [Select]

CREATE OBJECTTYPE FFUser (userName STRING, firstName STRING, lastName STRING, email STRING, active BOOLEAN, authDomain STRING, scriptAuthService STRING, groups GRABBAG /FFUserGroup, notif_ids GRABBAG /FFNotificationID, imageData BYTEARRAY)


2) use FFUserProtocol

This I have no experience with but here's a link

http://fatfractal.com/prod/fyi-user-management-part-i/

Hope this helps

27
NoServer Questions and Answers / Re: iOS ByteArrays/BLOBs
« on: February 26, 2014, 04:55:07 PM »
Just to clarify

The name of the class doesn't have to match objecttype in the FDDL just the clazz. So

FDDL

Code: [Select]

CREATE OBJECTTYPE SomeObject (data BYTEARRAY, other GRABBAG /<Collection>)


When you create the FatFractal instance

Code: [Select]

FatFractal * main = [[FatFractal alloc] initWithBaseUrl:@"https://.."];
           
[main registerClass:[MySomeObject class] forClazz:@"SomeObject"]; //Here the clazz matches the OBJECTTYPE not the class


NSObject Subclass

Code: [Select]

@import Foundation;

@interface MySomeObject : NSObject

@property (nonatomic, strong) NSData * data; //Here the property name matches the OBJECTTYPE description

//Just an FYI if you want grab bags to be serialized into the subclass declare them as a NSMutableArray property. You do need to use depthGB to retrieve them.

@property (nonatomic, strong) NSMutableArray * other;

@end


Here's the link to the documentation

http://fatfractal.com/prod/docs/datastore/#class-mapping

28
NoServer Questions and Answers / Re: iOS ByteArrays/BLOBs
« on: February 26, 2014, 04:21:03 PM »
Say you declared your object in the fddl like so

Code: [Select]
CREATE OBJECTTYPE SomeObject (data BYTEARRAY)

When you create your NSObject  subclass you type the BYTEARRAY as an NSData property

Code: [Select]

@interface SomeObject : NSObject

@property (nonatomic, strong) NSData * data;

@end


Using method 1 or 2 will place the blob in that NSData object. From there you can use whatever class method on NSData to write to disk.

Don't forget to register your subclass with FatFractal.

29
NoServer Questions and Answers / Re: iOS ByteArrays/BLOBs
« on: February 26, 2014, 11:37:14 AM »
There are three ways to approach downloading the file.

1) With the object

Here you can simply set the autoLoadBlobs on the FatFractal class and this will automatically download the blob with the object. IF global isn't desired you can use a FFReadRequest to handle this per query.

Code: [Select]

NSString * uri = ....

FFReadRequest * request = [[FatFractal main] newReadRequest];

[request prepareGetFromUri:uri];

[request executeAsyncWithOptions:FFReadOptionAutoLoadBlobs andBlock:^(FFReadResponse *response) {

NSArray * array =  response.objs;

}];


2) Delayed

Here you set the autoLoad blobs to no and this will dibble auto loading of blobs. You can use the readRequest as about or a FatFractal Class method to download the object with the blob at a later date.

Code: [Select]

_ff = [[FatFractal alloc] initWithBaseUrl:@"https://..."];
       
_ff.debug = YES;
       
_ff.autoLoadBlobs = NO;

...
...

id objectWithBlob = ...;

[[FatFractal main] loadBlobsForObj: objectWithBlob onComplete:^(NSError *theErr, id * theObWithBlob, NSHTTPURLResponse *theResponse) {


}];


3) Stream

Here you can exploit the fact that all object are accessible via their URI, now I've never tried this but I would assume you use NSURLConnection and the like to download the blob by giving it the URL to the object IE

https://<your domain>.fatfractal.com/<your application>/<collection>/<guid>/<blobMemberName>

Note this can be use for non streaming purposes as well, so you could use NSData's class method initWithContentsOfURL: to access the blob. I'm not sure how permissions is handle with this method.

Here's another forum post regarding streaming.

https://forum.fatfractal.com/forum/index.php?topic=69.0

30
NoServer Questions and Answers / Re: iOS ByteArrays/BLOBs
« on: February 26, 2014, 11:16:40 AM »
What exactly are you trying to do?


Pages: 1 [2] 3 4 5
Copyright © FatFractal customer forums