Cast a String to Timestamp in PostgreSQL

If storing a date/timestamp in a varchar or text field in postgres, the to_timestamp() function will let you access the value as a ‘real’ date. The second parameter tells the function the format of your string:

SELECT to_timestamp(‘2008-08-01′, ‘YYYY-MM-DD’) AS date;

Cocoa Bindings and NSPopUpButton

A frustrating problem I came across today when I tried binding an NSPopUpButton’s selection key to an NSArrayController’s selection was that the NSPopUpButton would always display a ‘ghost’ object -one of the opaque classes internal to Cocoa/Core-Data Bindings(<_NSControllerObjectProxy… or similar).

It turns out that NSPopUpButton does not record the user’s selection, so even if I had been able to get rid of the ghost object, I wouldn’t have been able to access the selected object.

The solution is to manually maintain a currently selected object in the window controller - File’s Owner in Interface Builder; in this case, selectedPackage:

In MyWindowController.m:

- (void)setSelectedPackage:(NSManagedObject *)package
{
// … checks …
selectedPackage = package;
}

- (NSManagedObject *)selectedPackage
{
return selectedPackage;
}

In Interface Builder, the NSPopUpButton should be bound to the NSArrayController (Packages) and the File’s Owner as:

Content: Packages.arrangedObjects
Content Values: Packages.arrangedObjects;modelPath=packageName
Selection: File’s Owner.selectedPackage

A default selection can then be provided by calling the setSelectedPackage: method.

Running Aptana Jaxer on Ubuntu 8.04

I’ve not had any time to try out Jaxer yet, but the idea of a single platform for both client and server-side processing sounds good.

On trying to get started, though, one problem I encountered was that the installation instructions on Aptana’s site didn’t quite get Jaxer running on my default Ubuntu 8.04 install. The reason seems to be the built-in Apache trying to load an external library from

/usr/lib

which doesn’t exist.

The library in question is libexpat.so.0; however, there is a libexpat.so.1.5.2 installed! You can check this by running:

$ ls -l /usr/bin | grep libexpat

Creating a link to this file in /usr/lib with:

$ ln -s libexpat.so.1.5.2 /usr/bin/libexpat.so.0

seems to have got Jaxer running and the server status looks good. If you’re having trouble getting a Jaxer server running on the latest Ubuntu, this might be worth giving a go.

Singleton Pattern in Javascript

At work, I have been developing a custom framework loosely based on my experience with the symfony and Propel. One of the requirements for the application under development is to store the application’s state both on the server and the client, so that information can be passed by means of AJAX requests.

To aid this process, each page controller PHP class has a corresponding Javascript class. In order to maintain state through the application, each class as a Singleton. With the help of Prototype, singleton classes are quick and easy to implement in Javascript:

First, declare the class itself using Prototype’s Class.create() method:

PageController = Class.create({
        /**
         * @type {integer}
         */

        userId: null,

        // … more properties …

        /**
         * Constructor
         */

        initialize: function()
        {
        // …
        },
       
        /**
         * A method to do something…
         */

        doSomething: function()
        {
                console.log(‘doSomething()’);
        },

        // … more methods …
});

Once the class is created, we can declare a static instance of the class and a static method, getInstance(), that will be used to return the single instance of the class:

/**
 * @type {PageController} Static instance of the page controller
 */

PageController.instance = null;

/**
 * Return the static (singleton) instance of
 * the page controller object
 */

PageController.getInstance = function()
{
        if(!PageController.instance)
                PageController.instance = new PageController()

        return PageController.instance;
}

With the class now declared, the singleton instance can be accessed in your application using the static getInstance() method:

PageController.getInstance().doSomething()

Gmail Contacts API

I noticed today that Google has finally launched an API for its contacts application. I’m sure I’m not alone in wanting to easily and properly synchronise contact data amongst Gmail, Address Book, mobile, etc. and use Gmail contacts as a single repository.

The API uses Google’s GData format, which is something I’m yet to look into. It would seem to be a‚ good time to put into practice some Python‚ - or maybe dust off the Objective-C - and‚ Cocoa.

An Example of Near-Perfect Design

I’ve been a long-time fan of Google Calendar, mainly because I can see where I need to be from any web connection. But probably its most useful feature is the thought that has obviously gone into the interaction design.

The Problem
When using calendar software, it is painful to have to click between each field, setting hours and minutes, locations etc. then confirming with an OK. I have been known (more often than not) to forego any form of calendar, instead relying on scrawl left on scraps of paper around the office. Whilst less organised than a calendar, this said scrawl is a lot easier to jot down. Needless to say, though, it is also a lot easier to lose.

A Solution
In Google Calendar, the designers have captured my need to quickly jot down when, where and who. No longer do I need to tab between fields, carefully tapping out 24-hour clocks (or 12-hours, depending the software’s mood). Instead, events can be entered as simply as:

meet joe at company friday 11am

Google Calendar will then automatically pick out the important information and add the appropriate event. No fussing around with mini-calendars or remembering to use mm/dd instead of dd/mm - the app just works. This is, for me at least, near-perfection user design - and I hope more software begins to take note (Apple’s new iCal 3.0 does not).

Google Calendar’s ‘Quick Add’ is an example of removing layers of abstraction (or barriers) between the user and the system, and quite correctly why should the user conform to the system? It should surely be the other way round. Mobile phone OS designers should note, why should it take 4 menu items to get to a message inbox? Perhaps Google’s new Android will help to iron that one out…

Core Data: Cached Transient Properites

In writing HostManager 2.0, I’ve come up against a lot of problems caused by the dark magic that is Cocoa bindings and key-value observing. One of the most troublesome of these has been with transient (calculated) properties.

For example, a Client managed object can get a count of owned domains that are expiring soon. This is a transient propety, accessed through a key of expiringDomains. It simply returns an NSSet which is built from a fetchRequest.

Previously, I was running this fetchRequest each time the key was accessed. This was admittedly inefficient, but seemed functional - at least until you saved the document.

Something crazy happens when a Core Data document is saved - all the objects in a context are released (faulted). There is a good reason for this, as it frees up any memory that was being used to temporarily store the managed objects. However, it caused very strange results to appear in my transient properties; namely, they would all vanish.

Even forcing the fetch request to refresh didn’t pick up any objects from the context (I’m not sure why as I would have expected the faulted objects to be ‘refired’). So I took the plunge and refactored the Client object to cache its expiringDomains value. After some extensive testing and finger-crossing, I’m fairly sure this is the correct way to handle transient relationship properties:

CustomManagedObject.h

@interface CustomManagedObject : NSManagedObject {
ame NSSet *transientRelationship;
}

- (NSSet *)transientRelationship;

CustomManagedObject.m

#import "CustomManagedObject.h"

@implementation CustomManagedObject 

- (void)awakeFromFetch
{
ame [super awakeFromFetch];

ame // set managed object to observe changes to the context, this is necessary
ame // to monitor changes to the context that occur elsewhere in the app
ame [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refresh:) name:NSManagedObjectContextObjectsDidChangeNotification object:[self managedObjectContext]];

ame // clear the cache after managed object is fetched into the context
ame if( transientRelationship != nil )
ame [transientRelationship release], transientRelationship = nil;}

- (void)refresh:(NSNotification *)notification
{
ame // ... perform check to see if update is neccessary, assume it is...

ame if( refreshNeeded ) {
ame if( expiringDomains != nil )
ame gDomains release], expiringDomains = nil;
ame }
}

- (NSSet *)transientRelationship
{
ame [self willAccessValueForKey:@"transientRelationship"]
ame
ame if( transientRelationship == nil ) {SFetchRequest *aFetchRequest = [[[NSFetchRequest alloc] init] autorelease];

ame [aFetchRequest setEntity:[NSEntityDescription entityForName:@"DestinationEntity" inManagedObjectContext:[self managedObjectContext]]];

ame // optionally, set a predicate, e.g. owner == self
ame [aFetchRequest setPredicate:[NSPredicate predicateWithFormat:@"predicateString"]];

ame NSArray *results = [[self managedObjectContext] executeFetchRequest:aFetchRequest error:nil];

ame transientRelationship = [[NSSet setWithArray:results] retain];
ame }
ame
ame [self didAccessValueForKey:@"transientRelationship"]

ame return transientRelationship;
}

Check your language for GMail IMAP?

Like quite a few others, I was pleased to hear that Google has finally got round to adding IMAP to its GMail service. IMAP means checking and dealing with emails from multiple sources is a lot simpler, as any changes are synchronised back to the server. I patiently waited for the IMAP tab to appear in my settings panel, as Google had announced it would take a few days to activate. After a couple of days, though, I began to wonder if they had forgotten about my one lonely GMail account, and starting browsing the help pages for any hint of what might be happening. By sheer luck, I happened upon this little nugget of info:

To use IMAP, you must have your interface language set to ‘English (US)’.Â

Just in case, I thought, I’d check my language settings. Lo and behold, my GMail account was set to use English-UK. I flicked the language back to English-US, and the IMAP option dutifully popped up in my settings panel.So, if you’re still waiting for IMAP to appear, it might pay to check that your account language settings.

Unfaulting Core Data Objects After Load

Hours of searching for an answer were beginning to lead me to the conclusion that it was impossible to unfault transient properties of an NSManagedObject after loading them from a datafile.

The Problem: A ’smart’ group to show expiring domains based on their (transient, calculated) isExpiring property worked until the document was saved. On saving, the objects in the context became faults and the smart group no longer worked. This was also true of re-loading a saved document - the domain’s isExpiring property would not be unfaulted.

ame

The Solution: It’s a horrible solution, but seemingly the only way to get the faults to fire (calling [domain will/didAccessValueForKey:@"isExpiring"] did nothing). On awakening the smart group from a fetch, a quick NSFetchRequest is created to fetch all the Domain objects and unfault their @”data” propety. This is no doubt a dirty piece of code, but seems to force the calculated properties to be unfaulted.

- (void)awakeFromFetch
{
ame [super awakeFromFetch];
ame [self commonAwake];
ame
ame NSError *error;
ame NSFetchRequest *fr = [[[NSFetchRequest alloc] init] autorelease];
ame [fr setEntity:[[self fetchRequest] entity]];
ame
ame NSArray *results = [[self managedObjectContext]
ame SEnumerator *enumerator = [results objectEnumerator];
ame id object;
ame
ame while( object = [enumerator nextObject] ) {
ame NSLog( [object valueForKey:@"domainName"] );
ame [object willChangeValueForKey:@"data"];
ame [object didChangeValueForKey:@"data"];
ame }
}

With this now working, I can finally continue implementing the business logic in HM2.0, and stop worrying about the intricacies of Core Data and the dark art of Bindings.