Learn ORM in Perl with DBIx::Class - Part 1

Wrap your database with OO abstraction

Kirk Lewis
Cultured Perl
4 min readFeb 4, 2017

--

source: https://www.flickr.com/photos/kirklewis/32579951031/

This post will provide a breif hands-on introduction to ORM in Perl using a few DBIx::Class sub classes.

In detail, this means we will generate Schema, Result and ResultSet classes (Perl modules) which will be used to interface with a SQLite database. The database will contain a single users table. Once the database has been created, we will implement functionality to both return the full name of a user, and find all users under a given age. To ensure the functionality of the schema, this code will be implemented using Test Driven Development (TDD), where the tests will be written first, then made to pass as we add new functionality.

This article is divided into two parts. The first part is doing the groundwork — installing Perl modules, setting up the directory structure, the database to test against, and a unit test against which we can measure our progress. In the second part we will create a database and use DBIx::Class modules to make the tests pass.

Prerequisites

  • Understanding of Object Relational Mapping (ORM)
  • Basic knowledge of Perl — including sub-routines, references, packages and of course, writing tests.
  • SQLite will be used to generate the database.
  • cpanm a CLI tool for downloading, building and installing Perl modules.
  • Perlbrew is optional but recommended as it’s good for managing module dependencies independently per project.

Getting Started

Start by creating a project directory and empty files where you’ll put your code. The simplest way to do this is to copy and paste the lines below into your terminal and then press enter.

This gives you a directory structure and files which looks like this:

Project Dependencies

The modules required for the tests and generating the class schema need to be added to the cpanfile and then installed.

Open the cpanfile and add the following modules.

Install Modules

From within the dbix-proj directory install the modules using the cpanm command.

The modules should now be installed.

Note: Depending on what you already have installed (and your bandwidth) this can take a few minutes minutes. This is because cpanm will run the tests which ship with each module. Scan ahead or go and make a coffee — you’ll see it’s well worth the wait!

To make sure these packages are found by Perl (if not using perlbrew) run this:

If you get an error message like:

then you need to update @INC to include the directory where the packages were installed:

The Database

Here we will create a database schema and later use it to create our class schema in part 2.

Writing the SQL

Open the file scripts/schema.sql and enter the following SQL statements.

Create the Database

Now lets create the database and its tables, and populate it with data in one go using SQLite. In the root directory enter the following command in your terminal.

Verify the Database

To verify the database schema has been created, open the app.db database as follows.

Now select all the users in the users table.

The results should read as follows

Writing a Test

Now some basic tests will be written to check whether our class schema exists and the modules within its namespace ‘work as intended’.

t/basic.t

Open the file t/basic.t and write the following:

And that’s our test. Although commented I will briefly explain the entire file.

First Test::More is imported so we can use its functions use_ok, can_ok and is which it exports. Each of these functions is used to prove a test case.

  • Next, our soon to be generated ‘App::Schema’ module is imported. Since it is not yet implemented the use_ok just below it will fail.
  • The next part is connecting to the database and creating a ResultSet instance for the User source. This is how we will interface with the user table in the second part of this article.
  • Finally the tests which follow use can_ok and is, to check whether a custom accessor fullname or method age_less_than have been defined first, before trying to use them.

Run the Test

Now let’s run the test using prove and the flags -l which means check the lib directory for modules, and -v to provide verbose output.

The test should fail and the output should look similar to this:

The failure occurred because there is no App::Schema defined since it has not been generated yet. This will be done in part 2.

Summary

The sections above focused on getting the project set up, so that in the next part we can just focus on generating the class schema. One important file that was created here is t/basic.t, our test file. This will be used throughout the second part to check whether everything is working as intended.

--

--