Tags: phoenix, elixir, crud, pharchive


Today we are going to get build a simple Phoenix CRUD (Create Read Update Destroy) application. Ultimately, we will be deploying this on Vultr but for now lets focus on some Phoenix basics with a practical goal: Making the best darn photo archive out there, Pharchive.



I am an amateur photographer and I have hundreds of pages of photographic negatives which I need to painstakingly keep track of, and make search-able. To aid me in this arduous task I am going to draw on Phoenix.

Pharchive’s data model

Let’s start small, we can always add features later. Here is a list of things that I want Pharchive to do:

This is a pretty straightforward set of Parent Child relationships, so this should be quick!

The models are going to be as follows:

A class diagram describing initial relationships in our data model

These are the type of models that Phoenix’s generators make easy, but first…

Scaffolding a new app

Move to where you would like to have the Pharchive project live in your directory structure, then run mix phoenix.new Pharchive. Don’t forget to answer Y to the question: “Fetch and install dependencies?”. cd Pharchive and run mix ecto.create, this makes sure that you have a database created for the Pharchive application.

At this point you have done all that is required to have a basic phoenix application which can respond to a web request. If you want to test this run mix phoenix.server -p 4000 (the -p 4000 is superfluous as mix phoenix.server defaults to using 4000, but I want to be sure not to lead you astray!) and visiting localhost:4000 in your browser or with curl.


Next up we are going to start at the top of our data model with Manufacturer. Manufacturers are film producers, at this point I don’t need to know anything more about them than just a name. Let’s use Phoenix generators to build up a simple CRUD interface for working with Manufacturers.

mix phoenix.gen.html Manufacturer manufacturers name:string

Next we will create the Film model. This is a fairly important piece, which has a few useful attributes.

mix phoenix.gen.html Film films speed:integer name:string short_name:string manufacturer_id:references:manufacturers

Finally we get to the real meaty model, which I am primarily concerned with: Collections.Collections are actual physical objects which I keep track of.

mix phoenix.gen.html Collection collections physical_id:integer uuid:uuid location:string frame_count:integer description:string taken_at:date frame_size:string film_id:references:films

Now that everything is all generated, we have to make sure that our application router has the new pages in place.

file: router.ex

Next, we must make sure that our associations are reflected in our models.

file: models/film.ex

file: models/manufacturer.ex

And finally, run a mix ecto.migrate to ensure that the database schema is up to date! With that, Pharchive has been properly setup and is ready for some upgrades.


The next step is automating UUID creation on a collection. Having to type in a fresh UUID for every collection is just going to get tedious. Luckily for us, this is a quick and easy change in web/models/collections.ex

And since we are relying on the application to generate these UUIDs, we can remove this whole form group from the collections form in web/templates/collection/form.eex. Go ahead and do that now.


In order to effectively manage our soon to arrive front end packages, we are going to need Bower installed. I like Bower; it is easy to understand, and it plays very nicely with phoenix.

Now that we have Bower installed, lets add some enhancements to our UI. Our form’s date pickers are atrocious. I think we should get something a bit more usable. I chose to use bootstrap-datepicker.

Since jQuery is a prerequisite, we are going to need to tell Bower to install both jquery and bootstrap-datepicker. We can do this by creating a bower.json file at the top of the Pharchive project tree.

The next time you fire up the Phoenix server you will see that bower fetches jquery and bootstrap-datepicker and makes them available to Phoenix. Next, we will initialize the datepicker in a new file web/static/js/datepicker.js


We only have a few more steps to see this bear fruit. Let’s import our new datepicker function in web/static/js/app.js

And finally, we need to add the datepicker class onto the date input that we want to clean up. In web/templates/collection/form.html.eex change the following line:


and boom, our datepicker is now working in the Collection form!

Thats all for today folks, you can review the repo and check out the working code here. Next time we will be working with forms!