Talks I’ve Given

These are some talks I’ve given. I’ve ordered them by most recent first. Some have more info than others, but hopefully, you’ll enjoy them and find them useful!


Working with Legacy Databases in Ecto

ElixirConf 2017 - Sep 7, 2017

Often when starting an Elixir or Phoenix project that is data-backed, there is an existing database that you need to interact with. There are plenty of tutorials about getting started with Ecto in a green project, but how do you take a legacy database and get it working in your new application? We’ll explore normal situations all the way to crazy ones like weird foreign keys and even dealing with multiple databases simultaneously!

Video

Slides

The slides are available as web pages here or embedded below. Click or press the right arrow to advance. I’m not super excited about this solution as it takes forever to load, but for now, this is the best I’ve come up with. Let me know if you have a better solution.

Example Code

  • To add an override for Ecto 2.2 to your Phoenix applications, make your deps function in your mix.exs file look like the following with override: true.

    defp deps do
      [
        {:phoenix, "~> 1.3.0"},
        {:phoenix_pubsub, "~> 1.0"},
        {:phoenix_ecto, "~> 3.2"},
        {:phoenix_html, "~> 2.10"},
        {:phoenix_live_reload, "~> 1.0", only: :dev},
        {:react_phoenix, "~> 0.4.0"},
    
        {:ecto, "~> 2.2.0-rc.1", override: true}, # <-- here
    
        {:gettext, "~> 0.11"},
        {:cowboy, "~> 1.0"},
        {:mariaex, "> 0.0.0"}
      ]
    end
    
  • If you’d like to make sure that the database structure file is dumped every time you migrate, add an alias for ecto.migrate to aliases in mix.exs.

    defp aliases do
      [
        "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
        "ecto.reset": ["ecto.drop", "ecto.setup"],
        "ecto.migrate": ["ecto.migrate", "ecto.dump"],
        "test": ["ecto.create --quiet", "ecto.migrate", "test"]
      ]
    end
    
  • To deal with using belongs_to with tables that have funky primary key names, you can use the source field option.

    defmodule F1Saver.API.Race do
      use Ecto.Schema
      alias F1Saver.API.Circuit
    
      schema "races" do
        field :year, :integer
        field :round, :integer
        field :name, :string
        field :date, :date
        field :url, :string
    
        belongs_to :circuit, Circuit, source: :circuitId # <-- HERE!
      end
    end
    
  • If you need to set a primary key that is something other than the default id, you can set the @primary_key module attribute.

    defmodule F1Saver.API.Race do
      use Ecto.Schema
      alias F1Saver.API.Circuit
    
      #            {fieldname, type, options}
      @primary_key {:id, :id, source: :raceId} # <-- here
    
      schema "races" do
        field :year, :integer
        field :round, :integer
        field :name, :string
        field :date, :date
        field :url, :string
    
        belongs_to :circuit, Circuit, source: :circuitId
      end
    end
    
  • If you have a table that doesn’t have a primary key at all, set @primary_key false.

    @primary_key false
    
  • To define a relationship between schemas but keep Ecto from defining a field, you can use the define_field: false field option. You can define those fields with your own options to use the data in those fields.

    field :race_id, :integer, source: :raceId
    field :driver_id, :integer, source: :driverId
    belongs_to :race, Race, foreign_key: :raceId, define_field: false
    belongs_to :driver, Driver, foreign_key: :driverId, define_field: false
    
  • To define your own custom Ecto type, you can create a module that implements the Ecto.Type behaviour.

    defmodule EncryptedField do
      @behaviour Ecto.Type
    
      def type, do: :binary
    
      def cast(string) when is_binary(string) do
        {:ok, Cipher.encrypt(string)}
      end
    
      def load(string) do
        {:ok, Cipher.decrypt(string)}
      end
    
      def dump(string) do
        {:ok, Cipher.encrypt(string)}
      end
    end
      
    defmodule F1Saver.API.Encrypt do
      use Ecto.Schema
    
      schema "encrypts" do
        field :text, EncryptedField
      end
    end
    
  • If you need to deal with database-defined schemas, use the @schema_prefix module attribute.

    defmodule F1Saver.API.Race do
      # ...
      @schema_prefix "f1"
      # ...
    end
    
  • If you’d like to use multiple database, you can define multiple repos. For example, in your config/config.exs file:

    use Mix.Config
    
    config :f1_saver, F1Saver.LegacyRepo,
      adapter: Ecto.Adapters.MySQL,
      database: "f1_legacy",
      username: "root",
      password: "something_secret",
      hostname: "legacy.mysite.com"
    
    config :f1_saver, F1Saver.Repo,
      adapter: Ecto.Adapters.Postgres,
      database: "f1",
      username: "root",
      password: "something_secret",
      hostname: "new_hotness.mysite.com"
    
    config :f1_saver, ecto_repos: [F1Saver.LegacyRepo, F1Saver.Repo]
    

Using Ecto Outside of Phoenix

Lonestar ElixirConf 2017 - Feb 10, 2017

Setting up Ecto outside of Phoenix is really simple and can be a great way to get started learning about Elixir. In this live-coding presentation, we will set up Ecto in a test project and dive into some of the great things about Ecto and how to use it.

Video


Live Coding FizzBuzz in Elixir

Full Stack lightning talk - Nov 3, 2016

A quick implementation of FizzBuzz in 5 lines of code to showcase some of the features of the Elixir language.

Video


An Intro to Ecto: Using Ecto in Non-Phoenix Elixir Projects

Full Stack - Aug 11, 2016

How to set up your application to use Elixir if without using Phoenix. This is an early version of the talk I ended up giving at Lonestar ElixirConf 2017.

Video