DEV Community

Noel Worden
Noel Worden

Posted on • Updated on

Elixir/Phoenix Project: Create First Schema & Run Tests in Docker


  • Create Destinations schema under Mapping context

Create Destinations schema under Mapping context

The goal for this next step was to establish the first schema in the project, with the intention to then write the tests, and finally the views. In my previous projects I had always done this by hand, starting with the migration, then the schema, and then the context; and that was the plan for this work as well. But, plans changed, pretty dramatically. Having the time to explore and hopefully improve on my workflows and knowledge base, I spent some time researching before diving into the code. That research -unsurprisingly- led me to the the Phoenix Context docs, which, led me to the phx.gen.html generator. I've known about generators, but I had no idea that a generator existed that did so much.

Initially I was on the fence about using the generator, on one hand it is incredibly convenient for the framework to generate every file necessary to get a schema running, tested, and browser-ready. On the other hand, having all the work done automatically can lead to problems down the road, like debugging, because I'm not as intimately familiar with generated files as I would be with files I typed out by hand. Similar to the common idea that most people learn coding principles much better if they type it all out instead of copy/pasting it from the source. Ultimately I decided to use the generator. I have enough experience with the files being generated that I didn't feel the need to write them all out by hand. I also felt that it would be beneficial to know all the necessary bases were covered, and have that as a pull request to utilize as a reference for future work that I may write without a generator.

The phx.gen.html generator takes four arguments. The first is the context module name, then the schema module name, third is the schema module's plural name (to be used as the table name), and, optionally, the last is the list of fields and corresponding types.

The schema I wanted to created had a good number of fields, my generation looked like this:

In that generation command, Mapping is the context, Destination is the schema module, destinations the table name, and lastly the list of fields and their types.

  • side note: That command could have been typed out as one long string, like:

    But by using the \ as an escape character, the command can be broken out over several lines to enhance readability.

This one generation command created the context, schema, migration, all tests, and all views. The output showed all the files created and then instructions on two more steps needed to complete the process:

Executing the first step from the instructions created all the default the routes for this schema. For this case, the entirety of the default routes works because I intended on utilizing them all. I confirmed the routes generated as expected with this command:

docker-compose exec web mix phx.routes

Which returned:

The second step in the instructions was to execute the migration created in the generation, creating the destinations table in the database.

With the exception of including null:false to a few the fields in the migration, all files created by the generator were good to go. I have some work to do to the generated html files, but that will be covered by a ticket down the road. After executing the migration command, I can navigate to localhost:4000/destinations and I see the index page of that schema, with the ability to create a new record, as well as all the other record manipulating functionality I expect. It's actually pretty amazing how much was accomplished with that phx.gen.html command. There are several mix.phx commands, all of course do something different, and save a lot of typing. They can be found in the Mix Tasks section of the Phoenix documentation, or by typing mix phx in the terminal.

Bonus - Running tests in the Docker container

My initial plan was to separate out this work, but since the tests were included in the files produced by the generator I decided to tackle this and include it in the pull request. I hit some bumps in the road when changing the database configurations in test.exs, to get the tests to run within the container. The process was involved enough that it warranted its own post. The high-level overview is that the hostname of the testing database needs to be "db" to run the tests in a container, but "localhost" for the tests to run in CI. The solution was to use System.get_env/2 in the database configuration logic, and add an env field in the CI testing configuration.

The update to the elixir.yml file took this step:

And added an environmental variable of DB_HOSTNAME:

Then the hostname field of the testing database configuration found at test.exs went from this:

To this:

Where System.get_env/2 is looking for the environmental variable set in the elixir.yml CI file. When that environmental variable is present (when tests are being run in the CI) it sets hostname to the variable's value, "localhost", allowing the tests to run in the CI build. And if the environmental variable is not found, the hostname defaults to "db", allowing for the test to properly run in a container.

Closing Thoughts

With the completion of this work, I can now Create, Read, Update, and Delete (CRUD) records in the destination table. The index view is currently a little rough, because of the size of the table that is being displayed, but that task is for another time. I can now also execute tests in the Docker container with this command:

docker-compose exec web mix test

And the tests also run as part of the CI check.

Having a working schema sets me up well for my next task, which is to utilize the seeds.exs file to populate the new table with sample data.

This is what my repo looks like at the end of this block of work.


This post is part of an ongoing series. I encourage any critique, feedback, or suggestions in the comments.

Top comments (0)