revisiting folders again some more

Posted on January 30, 2016

Having settled on a model for folders, I am (very slowly) changing the code to support it. One mildly annoying thing that hadn’t initially occurred to me is that I will actually need to migrate the live system from tags to folders, otherwise I’ll never be able to find my mail again. Still, that should only be a couple of lines of SQL.

Now. Here’s a major snag that I hit. I have been thinking that, since messages-folders is a many-many relation, why not allow a user to store a message in more than one folder? I confess I’ve been a bit vague about whether, from the user’s point of view, this would be i) useful, or ii) confusing, but I was up for implementing and finding out.

But. This introduces a serious problem with the move function. (And, indeed, delete, which is just moving to Waste, of course, although I haven’t got there yet.) If a message may appear in many folders, then to move it we need to know the message, the destination folder, and the source folder.

The only clean way to carry this information is in the URL. It would probably make sense to include the folder everywhere, so rather than:

http://flare.email/tag/General
http://flare.email/message/60558
http://flare.email/move/60558/Waste

we would have something like:

http://flare.email/m/General
http://flare.email/m/General/60558
http://flare.email/m/General/60558/move/Waste

This will all work, of course. It might make more sense to use the ID of the source folder rather than its name. That avoids problems with spaces and other funny characters. And it actually makes authorization quite straightforward: we just need to check if the authenticated user owns the folder.

When I set down to write this post, I thought I was going to conclude that I didn’t like this idea (let’s call it Scheme 2), but it’s not actually so bad.

The alternative is that we insist that each message appears in at most one folder for each user. Then, given a message and a user, we can deduce the unique folder it must be in. (As far as I can see this restriction cannot be expressed in SQL, unless we do something horrid like replicate the folder owner in the FoMe table, which is a pity.)

This is broadly similar to the existing scheme (so I’ll call it Scheme 1). It means we don’t have to mess with URLs, which admittedly is a minor consideration. It also means we won’t be able to conduct the one message in many folders experiment.

Now, is there anything wrong with Scheme 2, and one message in many folders? Yes, there really is. It works fine when we are viewing messages through folders. But of course, there are (or will be) other ways to view messages, such as tags and searches. Suppose I am looking at all my important messages, via a URL luch as:

http://flare.email/tag/important

One would expect to see a list of links to messages, very much like a folder view. But in Scheme 2, what on earth do the links look like? Either we have to pick an arbitrary folder of the (possibly) many, or we have folderless links, which then won’t allow you to do much with the message (not even delete it). Or, I suppose, we could list messages more than once (for every folder they were found in)!

No no no. This is compelling: one message in many folders is Just Wrong, and we don’t need Scheme 2. (I’m rather glad that I’ve thought this through now, and didn’t start implementing Scheme 2, only to make this dreadful discovery somewhere down the road.)

The only remaining question at this point is whether we can do anything to enforce one message in one folder (per user) in SQL. Obviously we could store user ids in the FoMe table, and enforce Unique Message User. But then we either have to duplicate the user id in the Folder table, or not. If we do, then we again have a condition that SQL cannot enforce. If we don’t, then we’re back to folders disappearing when empty.

Another idea has just occurred to me. Is it worth revisiting the idea that a message is shared between users by sharing the Message table entry? Dropping that would simplify things quite a bit. So long as we’re storing the actual messages outside the database, we can continue to share those. Hmm… I think I need another post to explore this one.