Usually we just use incrementing integers as primary keys on our database objects however in Coact we're using UUIDs instead.
To make things easy, there's a good little extension for Postgres which adds a
uuid column type and Rails supports using this without any additional work.
The primary reason we're using UUIDs is to allow any object in any of our tables to be uniquely identified just by its ID. Unlike numeric keys, where the object with ID
123 may exist in multiple tables, a UUID will only ever exist in one.
The fact each UUID is unique and relates to a single object allows us to easily pass references to objects around without worrying about also including the class/type of object involved.
Keeping track of UUIDs
To keep track of which table a specific UUID belongs to, we have a
UUID model which has two columns: the ID and the name of the model that UUID belongs to. We then add a new UUID each time we add an object and remove it when it's destroyed.
This then allows us to take a UUID and immediately find it from our database. A bit like this:
UUID.find('some-uuid-id') #=> A User UUID.find('some-other-uuid-id') #=> A Project
Redirecting HTTP Requests
Another handy thing is we can do is create paths like
/go/9be1f990-29bf-419e-a963-56889935aa70 to redirect to the appropriate URL within the application. For example, if the UUID entered is a user we may redirect to the user's profile page.
This is particularly useful when you don't want to commit too heavily to your routing scheme and want to make the decision when the request is made. For example, when we send out an email to alert someone to a new discussion, the link just goes to
/go/uuid and we convert that to
/projects/:project_uuid/discussions/:discussion_uuid when the request is made. This then opens up the possibility to move discussions between projects without breaking any existing links to the discussion in mediums we have no control over any longer.
We use UUID v4 which is generated by random numbers. It's quite unlikely that any duplicates will occur in our dataset but we do include a uniqueness validation to ensure the UUID isn't in use anywhere else in the application before we allow the object to be created.