In the last episode of my Elixir adventures, I messed with own-made Views and Controller to display hardcoded flight information for my FlightLog. This week I’ll try to show data based on the content of the database.
Phoenix doesn’t have built-in data access capabilities. But there’s awesome Ecto project, that’s sort of beefed up ORM. It reminds me Entity Framework (or good parts of it) in .NET or Rails. It supports multiple databases, although the default is Postgres. If you generated your Phoenix project by default and didn’t exclude Ecto, you should have everything you need to start. If no, refer to this guide
To add data access to FlightLog, I started the way, I would usually do in a web project. I installed the database (I went with Postgres), created some table, inserted some sample data. It was proven later, that it wasn’t a necessary step.
To build your first model, go to your project root and type for example:
$ mix phoenix.gen.html Flight flights date:datetime flight_number:string from:string to:string * creating priv/repo/migrations/20150409213440_create_flight.exs * creating web/models/flight.ex * creating test/models/flight_test.exs * creating web/controllers/flight_controller.ex * creating web/templates/flight/edit.html.eex * creating web/templates/flight/form.html.eex * creating web/templates/flight/index.html.eex * creating web/templates/flight/new.html.eex * creating web/templates/flight/show.html.eex * creating web/views/flight_view.ex * creating test/controllers/flight_controller_test.exs Add the resource to your browser scope in web/router.ex: resources "/flights", FlightController and then update your repository by running migrations: $ mix ecto.migrate
As you can see, this gave me a lot of stuff – a migration, a controller, a controller test, a model, a model test, a view, and a number of templates. It also instructs as to add new Controller to the router. Let’s do that.
I also removed recent additions, because they served the same purpose. I initially though I’ll just edit them, but Ecto surprised me by doing everything for me. Updated route file looks like that:
defmodule Flightlog.Router do use Flightlog.Web, :router pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers end pipeline :api do plug :accepts, ["json"] end scope "/", Flightlog do pipe_through :browser # Use the default browser stack resources "/flights", FlightController end # Other scopes may use custom stacks. # scope "/api", Flightlog do # pipe_through :api # end end
After that I run
mix ecto.migrate which executed migration file:
defmodule Flightlog.Repo.Migrations.CreateFlight do use Ecto.Migration def change do create table(:flights) do add :date, :datetime add :flight_number, :string add :from, :string add :to, :string timestamps() end end end
This created tables for me as defined in phoenix.gen.html. I noticed that database has some extra fields for basic journaling like
updated_at. I logged into the database and added some data just to have something to show and fired up my project again:
When you browse to the site, you’ll notice that not only I have a list of flights, but also buttons for actions like Edit, Delete or Add a new item. All generated for me and even with decent styling. That was a very nice surprise.
So first look at Ecto is very positively surprising. It created all the boilerplate code for me, but it is also a code that’s understandable and easy to edit. There seem not to be any underlying magic. If I need to change default behaviour I feel I wouldn’t have much problem doing that. We’ll see in future if practice will support those claims.