Validation of record uniqueness in Ruby on Rails application


In one of my previous posts, I wrote about important software design antipattern. In this post I will explain how to avoid it in Ruby on Rails application.

Important feature of any web application is to have in database unique objects. Uniqueness is usually defined using object properties. Simple example is user that is uniquely identified by email address.

So, in your code, you need to implement uniqueness check. What Ruby on Rails offers in that field? Here is official documentation on active record uniqueness feature:

This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index on both columns in your database.

Wait, what is this rambling about two database connections? Reality check for a tester. As a tester, you do not need to know how to write uniqueness check in Ruby on Rails application. But you should understand the concept of database connection and parallel client access to database. Databases (like Postgres or MS SQL) have uniqueness check mechanism, and those are unique database indexes. If you do not understand that concept, your responsibility is to learn about it. In this days using the Internet, this is not the problem. Do not hesitate to ask for help from developers. This is important concept, and sometimes it is easier to get the explanation from real person.

Here is Rails example how to write migration class, that will add unique index to my providers active record:

Note that index consists of two attributes, name and url.

And here is uniqueness check in controller class:

Here we check if postgres PG::UniqueViolation exception was thrown. Exception is thrown if unique index is violated on DATABASE LEVEL. That means that uniqueness is check in one central point, and that is your database engine.