Skip to content

dgoldhirsch/map

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MAP

This is a moronic little application to teach me how to use GUIDs as ActiveRecord ids. There are three model classes, and three corresponding controllers:

Event – as in, a to-do event or calendar event (except there ain’t anything in it except a name) User – as in a user of the system (but there is no authentication) Attendee – a joining table mapping Users to Events.

Every Event, User, and Attendee record has a unique GUID in its “id” column. Why? Because in my recent iCalendar/CalDAV investigations I found it useful for providing database-independent, unique keys for things such as Events that may live in several different databases and which must all refer to the same underlying, virtual “event.”

An Attendee record belongs to both an Event and a User, and has additional attributes characterizing the details about how that user is attending the event.

To Use Map

Start script/server and then visit the usual, RESTful controllers:

localhost:3000/Events localhost:3000/Users localhost:3000/Attendees In the case of Attendees, you must supply the GUID of a given Event and User. Go ahead–try it with some wacky string GUID that doesn’t exist in the Events or Users table. You won’t be prevented from doing this, and it will screw up the app. (See below for how/why you are allowed to screw up the app this way.)

What I Learned About GUIDs in the “id” Column of a Model

Several blogs recommended overriding or making use of ActiveRecord::Base::before_create, slamming a generated GUID into the id column. That turns out to be not quite right. First of all, overriding before_create (or any of the other callback methods) is wrong because you will lose the effect of any other before_create callback processing you might need for that model. And, your overriding def of before_create will NOT be invoked in any subclasses of the model.

The correct solution is to use the before_create macro to add a callback method or block to the chain of existing callbacks for before-create.

And, probably, it is better to create the Guid in the before_validation_on_create rather than before_create; because, after all, you will want the GUID safely installed in the “id” column before your validation hook is called.

Also: don’t just slam a new, unique GUID into the ID column. Do so only of the ID column is nil. This allows you to create objects with a given GUID value, something you’ll want to do when mocking/testing.

You will have to redefine the column type of “id” to be whatever type you want for your GUID values. I used a string, for maximum flexibility. You can do this by disabling the typical, generated “id” column and instead declaring an “id” column explicitly, in the migration.

Finally, because the “id” column is now declared explicitly, I had to specify explicitly that it should be indexed. One can only hope that the database system is smart enough to realize that this should be a PRIMARY INDEX (that is, the sorting basis of the records) rather than a SECONDARY INDEX (taking up much more space). There are probably options for this that I am unaware of (yet).

What I Learned About Foreign Keys in ActiveRecord

Basically, I learned that AR doesn’t provide foreign key constraints. Apparently, the Agile Web Development in Rails book shows how to do it using some hard-coded SQL that fits somewhere in the migration. But, a good friend of mine steered me instead to a gem called Foreigner that extends the migration DSL with enough foreign-key stuff for my simple application.

It wasn’t obvious (to me) how to test whether the foreign key constraints were working–or, more charitably, that I was using Foreigner correctly. The best I could find was a blog post suggesting querying the metadata from the database and verifying that the FK constraints are in place. That would have been OK, except for something I learned about SQLLite…

What I Learned About Foreign Keys in SQLLite

So, how/why are you able to create an Attendee with bogus Event and/or User GUIDs? Because (as I found out) although SQLLite allows the declaration of foreign key constraints, it ignores them. So, I guess I shouldn’t bother writing tests for this, eh? Or, I should move to a “real” DBMS.

About

ActiveRecord hacking

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published