14 Dec 2018

Configure the default ordering for your models using UUID for primary keys

TL;DR: In Rails 6 it’ll be possible to configure the implicit order column used by the first and last methods, handy if you use UUIDs for your primary keys.

You may be using UUIDs as the primary key type for your models in your Rails application. Andy Croll has a great post explaining why you might choose to do this.

If you do then you’re probably aware of one of the downsides, which is that calling ActiveRecord’s first and last finder methods to get the oldest or newest record leads to surprising results. This is because the implementations of first and last rely on the primary key being an auto-incrementing integer, so calling them on a model with UUIDs as primary key without an explicit order scope results in a seemingly random record being returned (in reality it’ll be the record with the numerically-highest or lowest UUIDs, but that’s unlikely to be of any help to anyone)

Whilst always being explicit and including an order scope when calling first and last is a good habit to develop, having a sensible default behaviour would also be nice. Thankfully that’ll be possible in Rails 6 where the implicit order used by the first and last finder methods will be configurable:

  class Post < ActiveRecord::Base
    self.implicit_order_column = "created_at"
  end
  

For more details here’s the pull request for this change.

Why not just use a default scopes?

You be tempted to solve this issue using a default scope instead, something like this:

  class Post < ActiveRecord::Base
    default_scope { order(:created_at) }
  end
  

Please don’t. Default scopes can lead to all sorts of strange bugs and confusing behaviour. For example, with the above default scope on the model you’ll find calling Post.order(:name) will behave in a surprising way: the records will be returned ordered by created_at and then name, rather than just by name.

A caveat

There is a caveat to be aware of if you configure the implicit order to a non-unique column such as the created_at timestamp: if you have two records that have identical timestamp then you have no guarantee that the database will return the same record every time you call the finder method. Given that Rails and PostgreSQL stores DateTimes with microsecond precision the chances of this happening are relatively small, but you should still be aware of it.

06 Jul 2018

Resources for creating useful revision histories

I gave a talk at Brighton Ruby today on revision histories and code maintainability (You can watch the video here). Below are more resources on the same subject for those of you that want to go deeper.

Talks

Get Off the Tightrope by Tom Stuart: A great talk from Tom Stuart in which he outlines remedies and strategies for dealing with large problems, including advice on how history hygiene can help. Highly recommend.

Telling Stories Through Your Commits by Joel Chippindale: Another great talk, this time from Joel Chippendale of Future Learn covering similar ideas to those covered in my talk.

Git-driven Refactoring: Ashley’s talk from Brighton Ruby is a fantastic talk that demonstrates some of the other benefits that can come from a well put together revision history.

Blog posts

A Note About Git Commit Messages by Tim Pope: This for me is the canonical blog post on how to write good commit messages. Essential reading.

Small Commits for Fun and Profit Part 1 and Part 2: Two fantastic blog posts that detail how to shape commits using git add --patch, git commit --amend and git rebase --interactive.

10 Git tips You Didn’t Know You Needed: More tips, this time from myself. This is a write-up of a lightning talk I gave at my local Ruby meetup.

How to Write the Perfect Pull Request: Another great blog post on putting together the perfect pull request by Keavy.

Every line of code is always documented: Mislav’s post was instrumental in my understanding of the usefulness of a well put together history and the ways Git can be used to dig through one.

Other resources

Flight rules for Git: A comprehensive and succinct primer containing step-by-step actions for performing common Git actions.

Git Ready: Includes a breakdown of beginner/intermediate/advanced Git techniques, useful if you’re looking to learn something new to level up your Git abilities.

GIT.WTF!?: Similar to the flight rules, full of tips covering common problems and questions people face when working with Git.

View older posts »